v0.7.99-beta - "gekoppeld" zei niets over wat de container ziet
Some checks failed
Deploy server-up (dev) / deploy (push) Has been cancelled

De koppelingscontrole in --doctor keek of het pad in /proc/self/mountinfo
voorkwam. Een bind mount wijst echter naar een inode, niet naar een pad: is de
map op de host vervangen nadat de container was aangemaakt, dan kijkt de
container naar de oude en meestal lege map terwijl het pad nog netjes in de
mountlijst staat.

- --doctor telt nu aan beide kanten en vergelijkt
- onderscheidt "map bestaat niet in de container" van "map is leeg"
- staat er buiten wel iets en binnen niet, dan is dat een fout met de weg
  terug erbij (docker compose up -d --force-recreate)

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q9eqpADJSRs49SoGGr4NAy
This commit is contained in:
Ramon 2026-08-03 20:43:12 +02:00
parent 299ccf507c
commit 3fd6c19409
4 changed files with 74 additions and 10 deletions

View file

@ -1,3 +1,24 @@
# v0.7.99-beta — "Gekoppeld" zei niets
`--doctor` meldde vrolijk dat `/opt/serverup` in de container gekoppeld was,
terwijl Server Up daar geen enkele app zag en er buiten de container drie
stonden. De controle keek of het pad in `/proc/self/mountinfo` voorkwam, en dat
is precies de verkeerde vraag.
Een bind mount wijst naar een **inode**, niet naar een pad. Wordt de map op de
host vervangen nadat de container is aangemaakt — verwijderd en opnieuw
aangemaakt — dan blijft de container naar de oude, losgekoppelde map kijken.
Meestal is die leeg. Het pad staat dan nog gewoon in de mountlijst, dus
"gekoppeld" blijft er stralend staan terwijl je hele appslijst leeg is.
`--doctor` telt nu aan beide kanten en vergelijkt:
- bestaat de map binnen de container überhaupt?
- staan er buiten wél apps en binnen niet? Dan is de koppeling verouderd, en
staat erbij hoe je hem herstelt (`docker compose up -d --force-recreate`)
- is hij aan beide kanten leeg, dan is er simpelweg nog niets geïnstalleerd —
een waarschuwing, geen fout
# v0.7.98-beta — Het heet nu gewoon een app
Je installeerde een **app** uit de **App Store** en kreeg een **stack**. Dat

View file

@ -1 +1 @@
0.7.98-beta
0.7.99-beta

View file

@ -1172,16 +1172,32 @@ PYEOF
log "Stacks: $_lib"
log "Appdata: $_dat"
if [ -n "$_lib" ]; then
_n="$($SUDO docker exec server-up sh -c \
"ls -1 '$_lib' 2>/dev/null | wc -l" 2>/dev/null || echo 0)"
_n="$(printf '%s' "$_n" | tr -d '[:space:]')"
if [ "${_n:-0}" -gt 0 ] 2>/dev/null; then
dok_ok "$_n stack(s) zichtbaar voor Server Up"
# Bestaat de map daarbinnen überhaupt, en zo ja: staat er hetzelfde
# in als erbuiten? Dat laatste is de vraag die ertoe doet. Een bind
# mount wijst naar een inode, niet naar een pad: is de map op de
# host ná het aanmaken van de container vervangen, dan blijft de
# container naar de oude — meestal lege — map kijken. Het pad staat
# dan nog gewoon in /proc/self/mountinfo, dus "gekoppeld" zegt niets.
if ! $SUDO docker exec server-up test -d "$_lib" 2>/dev/null; then
dok_fout "De map $_lib bestaat niet binnen de container"
log " Hercreëer de container: $SUDO docker compose -f $DOEL/docker-compose.yml up -d --force-recreate"
else
dok_fout "Server Up ziet geen enkele stack in $_lib"
[ "$_lib" != "$_basis/stacks" ] \
&& log " Je stacks staan waarschijnlijk in $_basis/stacks." \
&& log " Pas LIBRARY_DIR aan bij Instellingen → Paden."
_n="$($SUDO docker exec server-up sh -c \
"ls -1A '$_lib' 2>/dev/null | wc -l" 2>/dev/null || echo 0)"
_n="$(printf '%s' "$_n" | tr -d '[:space:]')"
_h="$(ls -1A "$_lib" 2>/dev/null | wc -l)"
_h="$(printf '%s' "$_h" | tr -d '[:space:]')"
if [ "${_n:-0}" -gt 0 ] 2>/dev/null; then
dok_ok "$_n app(s) zichtbaar voor Server Up"
elif [ "${_h:-0}" -gt 0 ] 2>/dev/null; then
dok_fout "Buiten de container staan er $_h in $_lib, binnen de container geen"
log " De koppeling wijst naar een oudere map dan die er nu staat."
log " Dat gebeurt als $_basis op de host is vervangen nadat de"
log " container was aangemaakt. Hercreëren lost het op:"
log " $SUDO docker compose -f $DOEL/docker-compose.yml up -d --force-recreate"
else
dok_waar "Er staat nog geen enkele app in $_lib"
fi
fi
fi
# De app store leest uit de git-cache; is die leeg, dan is de lijst leeg.

View file

@ -1171,3 +1171,30 @@ def test_reconfigure_zonder_installatie_stopt(tmp_path):
r = _draai("--reconfigure", "--dir", str(tmp_path / "bestaatniet"))
assert r.returncode != 0
assert "Geen installatie gevonden" in r.stderr
# ── Een koppeling die er is maar niets laat zien ─────────────────────────────
# Een bind mount wijst naar een inode, niet naar een pad. Wordt de map op de
# host vervangen nadat de container is aangemaakt, dan kijkt de container naar
# de oude — meestal lege — map. Het pad staat dan nog gewoon in
# /proc/self/mountinfo, dus alleen daarop controleren zegt niets.
def test_doctor_vergelijkt_beide_kanten_van_de_koppeling():
tekst = SCRIPT.read_text(encoding="utf-8")
blok = tekst[tekst.index("Wat Server Up zelf ziet"):]
blok = blok[:blok.index("\n printf ")]
assert "ls -1A" in blok, "de inhoud wordt nergens geteld"
assert blok.count("ls -1A") >= 2, \
"er wordt maar aan één kant geteld; juist het verschil is de diagnose"
assert "--force-recreate" in blok, "er staat geen uitweg bij"
def test_doctor_onderscheidt_ontbrekend_van_leeg():
""""De map bestaat niet in de container" en "de map is leeg" hebben een
andere oorzaak en een andere oplossing."""
tekst = SCRIPT.read_text(encoding="utf-8")
blok = tekst[tekst.index("Wat Server Up zelf ziet"):]
blok = blok[:blok.index("\n printf ")]
assert "test -d" in blok, "er wordt niet gekeken of de map er is"
assert "bestaat niet binnen de container" in blok
assert "nog geen enkele app" in blok