server-up/tests/test_compose_transform.py
Ramon 8b29553a71
Some checks failed
Deploy server-up (dev) / deploy (push) Failing after 3s
v0.5.00-beta - containerbeheer, eigen IP-adressen, veiliger installeren
- 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
2026-07-26 14:51:32 +02:00

86 lines
2.7 KiB
Python

"""Poorten → eigen IP-adres (macvlan/ipvlan)."""
import sys
from pathlib import Path
import pytest
import yaml
sys.path.insert(0, str(Path(__file__).resolve().parent.parent / "server-up"))
from core import compose_transform as ct
BASIS = """\
services:
vaultwarden:
image: vaultwarden/server:latest
ports:
- "8222:80"
volumes:
- /data:/data
"""
def test_poorten_verdwijnen_en_ip_wordt_toegekend():
doc = yaml.safe_load(ct.to_dedicated_ip(BASIS, "lan", "192.168.1.240"))
svc = doc["services"]["vaultwarden"]
assert "ports" not in svc
assert svc["networks"] == {"lan": {"ipv4_address": "192.168.1.240"}}
assert doc["networks"] == {"lan": {"external": True}}
def test_overige_instellingen_blijven_intact():
doc = yaml.safe_load(ct.to_dedicated_ip(BASIS, "lan", "192.168.1.240"))
svc = doc["services"]["vaultwarden"]
assert svc["image"] == "vaultwarden/server:latest"
assert svc["volumes"] == ["/data:/data"]
def test_alleen_de_publicerende_service_krijgt_het_ip():
tekst = """\
services:
db:
image: postgres
web:
image: nginx
ports:
- "8080:80"
"""
doc = yaml.safe_load(ct.to_dedicated_ip(tekst, "lan", "10.0.0.5"))
assert doc["services"]["web"]["networks"] == {"lan": {"ipv4_address": "10.0.0.5"}}
# De database blijft in hetzelfde netwerk zodat web hem kan vinden.
assert doc["services"]["db"]["networks"] == ["lan"]
assert "ports" not in doc["services"]["db"]
def test_expliciete_service_kan_gekozen_worden():
tekst = "services:\n a:\n image: x\n b:\n image: y\n ports: ['1:1']\n"
doc = yaml.safe_load(ct.to_dedicated_ip(tekst, "lan", "10.0.0.9", only_service="a"))
assert doc["services"]["a"]["networks"] == {"lan": {"ipv4_address": "10.0.0.9"}}
assert doc["services"]["b"]["networks"] == ["lan"]
def test_zonder_poorten_krijgt_de_eerste_service_het_ip():
doc = yaml.safe_load(ct.to_dedicated_ip(
"services:\n solo:\n image: x\n", "lan", "10.0.0.2"))
assert doc["services"]["solo"]["networks"] == {"lan": {"ipv4_address": "10.0.0.2"}}
@pytest.mark.parametrize("tekst,fout", [
("dit: [is geen: geldige yaml", "geldige YAML"),
("version: '3'\n", "geen services"),
("- een\n- lijst\n", "mapping"),
])
def test_foutmeldingen(tekst, fout):
with pytest.raises(ct.TransformError) as e:
ct.to_dedicated_ip(tekst, "lan", "10.0.0.1")
assert fout in str(e.value)
def test_onbekende_service_geeft_fout():
with pytest.raises(ct.TransformError):
ct.to_dedicated_ip(BASIS, "lan", "10.0.0.1", only_service="bestaat-niet")
def test_published_ports():
assert ct.published_ports(BASIS) == ["8222:80"]
assert ct.published_ports("services:\n a:\n image: x\n") == []