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
86 lines
2.7 KiB
Python
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") == []
|