Initial commit - podman-mvp net na toevoegen cpu en mem kolommen
This commit is contained in:
@@ -0,0 +1,168 @@
|
||||
import os
|
||||
import sys
|
||||
import types
|
||||
import importlib
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
|
||||
class FakeResponse:
|
||||
def __init__(self, status_code: int = 200, json_data=None, text_data: str | None = None):
|
||||
self.status_code = status_code
|
||||
self._json_data = json_data
|
||||
self._text_data = text_data
|
||||
|
||||
def json(self):
|
||||
return self._json_data
|
||||
|
||||
@property
|
||||
def text(self):
|
||||
if self._text_data is not None:
|
||||
return self._text_data
|
||||
# Best-effort string
|
||||
return ""
|
||||
|
||||
|
||||
class FakeSession:
|
||||
"""
|
||||
Test-only Podman session stub.
|
||||
Routes by URL substring to return deterministic JSON.
|
||||
"""
|
||||
def __init__(self):
|
||||
self.calls = []
|
||||
|
||||
def get(self, url: str):
|
||||
self.calls.append(("GET", url))
|
||||
|
||||
# Pods list (DYNAMIC)
|
||||
if "/libpod/pods/json" in url:
|
||||
return FakeResponse(200, json_data=[])
|
||||
|
||||
# Containers list (DYNAMIC)
|
||||
if "/libpod/containers/json" in url:
|
||||
return FakeResponse(200, json_data=[])
|
||||
|
||||
# Container inspect (DYNAMIC)
|
||||
if "/libpod/containers/" in url and url.endswith("/json"):
|
||||
# Return some dict to prove JSON
|
||||
return FakeResponse(200, json_data={"Id": "dummy"})
|
||||
|
||||
# Container logs (FIXED endpoint expects {"logs": "..."} from wrapper endpoint, not Podman directly,
|
||||
# but app.py fetches Podman logs and then wraps into {"logs": text}.
|
||||
if "/libpod/containers/" in url and "/logs?" in url:
|
||||
return FakeResponse(200, json_data=None, text_data="line1\nline2\n")
|
||||
|
||||
# Fallback: return JSON dict
|
||||
return FakeResponse(200, json_data={})
|
||||
|
||||
def post(self, url: str, **kwargs):
|
||||
self.calls.append(("POST", url, kwargs))
|
||||
|
||||
# kube/play passthrough (workloads deploy)
|
||||
if "/libpod/kube/play" in url:
|
||||
# app.py gebruikt SESSION.post(url, data=yaml_content).json()
|
||||
return FakeResponse(200, json_data={"kube": "played"})
|
||||
|
||||
# Container start/stop/restart: treat as success
|
||||
if "/libpod/containers/" in url:
|
||||
return FakeResponse(204, json_data={})
|
||||
|
||||
# Pod start/stop etc: treat as success
|
||||
if "/libpod/pods/" in url:
|
||||
return FakeResponse(200, json_data={"ok": True})
|
||||
|
||||
return FakeResponse(200, json_data={})
|
||||
|
||||
|
||||
def delete(self, url: str):
|
||||
self.calls.append(("DELETE", url))
|
||||
return FakeResponse(200, json_data={"deleted": True})
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def app_module():
|
||||
"""
|
||||
Import app.py as module `app` from /app, while ensuring requests_unixsocket import is safe.
|
||||
No runtime changes to app.py; only test-time monkeypatching later.
|
||||
"""
|
||||
# Ensure /app is importable
|
||||
if "/app" not in sys.path:
|
||||
sys.path.insert(0, "/app")
|
||||
|
||||
# If requests_unixsocket isn't installed or to avoid real socket usage, provide a minimal stub.
|
||||
if "requests_unixsocket" not in sys.modules:
|
||||
mod = types.ModuleType("requests_unixsocket")
|
||||
mod.Session = lambda: FakeSession()
|
||||
sys.modules["requests_unixsocket"] = mod
|
||||
|
||||
app = importlib.import_module("app")
|
||||
return app
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def client(app_module, monkeypatch, tmp_path):
|
||||
"""
|
||||
TestClient with all external side-effects stubbed:
|
||||
- Podman socket calls via app.SESSION
|
||||
- systemctl calls via app.run
|
||||
- filesystem roots via WORKLOADS_DIR + ALLOWLIST_FILE
|
||||
"""
|
||||
# Prepare temp workload tree under tmp_path
|
||||
workloads_dir = tmp_path / "workloads"
|
||||
systemd_dir = workloads_dir / "systemd"
|
||||
systemd_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# A defined container (*.container) for /containers-dashboard defined entry
|
||||
(systemd_dir / "sonarr.container").write_text("[Container]\nImage=dummy\n", encoding="utf-8")
|
||||
|
||||
# Files endpoints operate under WORKLOADS_DIR; UI focuses on systemd subtree
|
||||
# Create a file for /files/read/save/delete
|
||||
(systemd_dir / "test.txt").write_text("hello\n", encoding="utf-8")
|
||||
|
||||
# Create a non-empty dir for /files/rmdir 409 scenario
|
||||
nonempty_dir = systemd_dir / "nonempty"
|
||||
nonempty_dir.mkdir(parents=True, exist_ok=True)
|
||||
(nonempty_dir / "keep.txt").write_text("x", encoding="utf-8")
|
||||
|
||||
# Create a yaml to create a defined pod entry for /pods-dashboard
|
||||
(workloads_dir / "mediaserver.yaml").write_text("kind: Pod\nmetadata:\n name: mediaserver\n", encoding="utf-8")
|
||||
|
||||
# Allowlist file for /systemd/allowlist and allow-mode enforcement
|
||||
allowlist_file = tmp_path / "allowed_units.txt"
|
||||
allowlist_file.write_text("sonarr.service\nmediaserver.service\n", encoding="utf-8")
|
||||
|
||||
# Patch module globals to point at tmp filesystem (test-only)
|
||||
monkeypatch.setattr(app_module, "WORKLOADS_DIR", str(workloads_dir))
|
||||
monkeypatch.setattr(app_module, "ALLOWLIST_FILE", str(allowlist_file))
|
||||
|
||||
# Stub Podman session object
|
||||
monkeypatch.setattr(app_module, "SESSION", FakeSession())
|
||||
|
||||
# Stub systemctl runner
|
||||
def fake_run(cmd):
|
||||
# cmd is a list, e.g. ["systemctl","--user","is-active","mediaserver.service"]
|
||||
cmd_str = " ".join(cmd)
|
||||
|
||||
if "is-active mediaserver.service" in cmd_str:
|
||||
return 0, "active"
|
||||
if "is-active sonarr.service" in cmd_str:
|
||||
return 0, "inactive"
|
||||
|
||||
# For POST /{action}/{unit}, return something stable
|
||||
if cmd[:3] == ["systemctl", "--user", "status"]:
|
||||
return 0, "Active: active (running)"
|
||||
if cmd[:3] == ["systemctl", "--user", "daemon-reload"]:
|
||||
return 0, "ok"
|
||||
if cmd[:3] == ["systemctl", "--user", "start"]:
|
||||
return 0, "started"
|
||||
if cmd[:3] == ["systemctl", "--user", "stop"]:
|
||||
return 0, "stopped"
|
||||
if cmd[:3] == ["systemctl", "--user", "restart"]:
|
||||
return 0, "restarted"
|
||||
|
||||
# fallback
|
||||
return 0, "ok"
|
||||
|
||||
monkeypatch.setattr(app_module, "run", fake_run)
|
||||
|
||||
return TestClient(app_module.app)
|
||||
Reference in New Issue
Block a user