Some checks failed
Deploy server-up (dev) / deploy (push) Failing after 3s
- Beheer per container: de stackkaart klapt uit naar de losse containers, met start/stop/herstart, logs en live CPU-/geheugengebruik per container. De containernaam wordt getoetst aan compose_ps van díé stack, zodat de route geen willekeurige container op de host kan raken. - Stacks met een eigen IP-adres (macvlan/ipvlan): netwerkbeheer onder Instellingen → Netwerken, netwerkkeuze in de installatiemodal met voorstel voor het eerstvolgende vrije adres, en automatische omzetting van het gerenderde compose-bestand (poortmappings eruit, ipv4_address erin). De templates in apps/ blijven ongewijzigd. - Toegekende IP's worden vastgehouden in .serverup.json en getoond op de stackkaart, zodat een volgende installatie ze niet opnieuw uitdeelt. - Vrije poort voorstellen bij installeren: next_free_port() bestond al maar werd nergens gebruikt. Bezette poorten worden in de UI gemeld. - Genereerknop voor velden die op een geheim wijzen (token/password/secret), lokaal gegenereerd via crypto.getRandomValues. - Compose valideren met `docker compose config` vóór het wegschrijven, zowel bij de editor als na het renderen bij installatie. Ontbreekt de compose-CLI, dan blokkeert dat een installatie niet. - Uitloggen in de zijbalk; gebruikersbeheer en wachtwoord wijzigen onder Instellingen → Beveiliging. - docs/netwerken.md (incl. de shim-interface die de host nodig heeft om zijn eigen macvlan-containers te bereiken) en docs/beveiliging.md toegevoegd. - CHANGELOG bijgewerkt; testsuite uitgebreid naar 112 tests. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C7oLCRYzY5ixJ5Sv8Y8EFb
82 lines
3.1 KiB
Python
82 lines
3.1 KiB
Python
"""Routes rond stacks: containerbeheer en de netwerkkeuze bij installeren."""
|
|
from conftest import login
|
|
|
|
|
|
def test_containers_van_onbekende_stack(client):
|
|
login(client)
|
|
r = client.get("/api/stacks/bestaatniet/containers")
|
|
assert r.status_code == 404
|
|
|
|
|
|
def test_containeractie_alleen_binnen_eigen_stack(client):
|
|
"""De containernaam wordt getoetst aan compose_ps van díé stack, zodat deze
|
|
route nooit een willekeurige container op de host kan raken."""
|
|
csrf = login(client)
|
|
r = client.post("/api/stacks/mijnstack/containers/traefik/stop",
|
|
headers={"X-CSRF-Token": csrf})
|
|
assert r.status_code == 404
|
|
assert "hoort niet bij deze stack" in r.get_json()["msg"]
|
|
|
|
|
|
def test_onbekende_containeractie(client):
|
|
csrf = login(client)
|
|
r = client.post("/api/stacks/mijnstack/containers/web/verwijder",
|
|
headers={"X-CSRF-Token": csrf})
|
|
assert r.status_code == 400
|
|
|
|
|
|
def test_containerlogs_alleen_binnen_eigen_stack(client):
|
|
login(client)
|
|
r = client.get("/api/stacks/mijnstack/containers/vreemde/logs")
|
|
assert r.status_code == 404
|
|
|
|
|
|
def test_install_weigert_onbekend_netwerk(client):
|
|
csrf = login(client)
|
|
r = client.post("/api/store/install",
|
|
json={"stack": "vaultwarden", "repo_id": "server-up",
|
|
"instance": "vw", "network": "bestaatniet"},
|
|
headers={"X-CSRF-Token": csrf})
|
|
assert r.status_code == 400
|
|
assert "niet geconfigureerd" in r.get_json()["msg"]
|
|
|
|
|
|
def test_install_weigert_ip_buiten_subnet(client, env):
|
|
csrf = login(client)
|
|
env["core"].patch({"NETWORKS": [{
|
|
"name": "lan", "driver": "macvlan", "parent": "eth0",
|
|
"subnet": "192.168.1.0/24", "gateway": "192.168.1.1"}]})
|
|
r = client.post("/api/store/install",
|
|
json={"stack": "vaultwarden", "repo_id": "server-up",
|
|
"instance": "vw", "network": "lan", "ip": "10.9.9.9"},
|
|
headers={"X-CSRF-Token": csrf})
|
|
assert r.status_code == 400
|
|
assert "buiten het subnet" in r.get_json()["msg"]
|
|
|
|
|
|
def test_netwerk_toevoegen_valideert(client):
|
|
csrf = login(client)
|
|
r = client.post("/api/networks",
|
|
json={"name": "lan", "driver": "macvlan",
|
|
"parent": "eth0; id", "subnet": "192.168.1.0/24"},
|
|
headers={"X-CSRF-Token": csrf})
|
|
assert r.status_code == 400
|
|
|
|
|
|
def test_netwerk_verwijderen_onbekend(client):
|
|
csrf = login(client)
|
|
r = client.delete("/api/networks/bestaatniet", headers={"X-CSRF-Token": csrf})
|
|
assert r.status_code == 404
|
|
|
|
|
|
def test_gereserveerde_ips_worden_gelezen_uit_stacks(client, env):
|
|
"""Een geïnstalleerde stack houdt zijn adres, ook als hij gestopt is."""
|
|
import json
|
|
login(client)
|
|
stack = env["lib"] / "vaultwarden"
|
|
stack.mkdir()
|
|
(stack / ".serverup.json").write_text(json.dumps({"ip": "192.168.1.241"}))
|
|
import app as app_module
|
|
with app_module.app.test_request_context():
|
|
assert "192.168.1.241" in app_module._reserved_ips()
|
|
assert "192.168.1.241" not in app_module._reserved_ips(exclude_stack="vaultwarden")
|