v0.10.10-beta - drie fouten in het installatiescript
Some checks failed
Deploy server-up (dev) / deploy (push) Failing after 3m28s
Some checks failed
Deploy server-up (dev) / deploy (push) Failing after 3m28s
- vragen werden bij `curl | sh` niet gesteld en zelf met "ja" beantwoord: vraag() keek naar stdin (de pipe) in plaats van naar /dev/tty. Docker werd daardoor van get.docker.com gehaald zonder dat het gevraagd was en --uninstall brak af zonder bevestiging. Eén terminal_beschikbaar() voor alle vijf de plekken - met --bind <eigen ip> mislukten de healthcheck en het aanmaken van het beheerdersaccount, omdat het script altijd 127.0.0.1 vroeg terwijl compose op $BIND publiceert; het controleadres volgt nu $BIND, met blokhaken om IPv6 - een mislukte update meldde "Bijgewerkt." met exitcode 0; hij stopt nu met een foutmelding, en een verse installatie zegt in het slot eerlijk dat er niet geantwoord is - curl kreeg tijdslimieten bij het pollen, zodat het aantal pogingen weer iets betekent; SU_WACHT_POGINGEN maakt het instelbaar - het slot noemde nog "beheert Docker als root" en toont nu het account Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q9eqpADJSRs49SoGGr4NAy
This commit is contained in:
parent
a7b00fc82b
commit
afda654983
5 changed files with 283 additions and 20 deletions
44
CHANGELOG.md
44
CHANGELOG.md
|
|
@ -1,3 +1,47 @@
|
|||
# v0.10.10-beta — Het installatiescript loog op drie plekken
|
||||
|
||||
Een controle van het hele installatiepad leverde drie fouten op die alledrie op
|
||||
`curl … | sh` liggen — de regel die de README noemt.
|
||||
|
||||
**Vragen werden niet gesteld en beantwoordden zichzelf met "ja".** `vraag()`
|
||||
keek naar stdin, en bij `curl … | sh` is dat de pipe. Alle andere prompts in het
|
||||
script gebruiken `/dev/tty`, dat gewoon bereikbaar is. Gevolg: "Nu installeren
|
||||
via het officiële script van docker.com?" werd overgeslagen en met ja
|
||||
beantwoord, `--uninstall` brak je installatie af zonder bevestiging, en de vraag
|
||||
of je een beheerdersaccount wilde bleef ongesteld terwijl de vervolgprompt
|
||||
("Gebruikersnaam:") wél verscheen. Er is nu één `terminal_beschikbaar()` die
|
||||
alle vijf de plekken gebruiken.
|
||||
|
||||
**Met een eigen bind-adres mislukte de healthcheck én het beheerdersaccount.**
|
||||
Compose publiceert op `$BIND`, maar het script vroeg altijd `127.0.0.1`. Met
|
||||
`--bind 10.0.20.5` luistert daar niets, dus meldde het "reageerde niet binnen
|
||||
anderhalve minuut" en daarna "Server Up was niet bereikbaar; account niet
|
||||
aangemaakt" — terwijl alles draaide. Je hield een installatie over zonder
|
||||
account, precies het venster waar het script voor waarschuwt. Het controleadres
|
||||
volgt nu `$BIND`, met blokhaken om IPv6.
|
||||
|
||||
**Een mislukte update meldde zich als geslaagd.** `wacht_op_gereed || true`
|
||||
gevolgd door `goed "Bijgewerkt."` maakte een kapotte update niet te
|
||||
onderscheiden van een goede, ook niet aan de exitcode. Nu stopt hij met een
|
||||
foutmelding en de weg terug. Bij een verse installatie gaat hij wél door — die
|
||||
aanwijzingen zijn juist dán nuttig — maar het slot zegt eerlijk dat er niet
|
||||
geantwoord is en de exitcode is 1.
|
||||
|
||||
Verder:
|
||||
|
||||
- `curl` kreeg tijdslimieten bij het pollen. Zonder die limieten bleef hij
|
||||
hangen op een adres waar niets naartoe routeert en betekende het aantal
|
||||
pogingen niets. Het aantal is nu ook instelbaar met `SU_WACHT_POGINGEN`, voor
|
||||
trage machines.
|
||||
- Het slot zei nog "Server Up beheert Docker als root" en noemt nu onder welk
|
||||
account het draait.
|
||||
|
||||
Onderweg gevonden en meteen verholpen: de eerste versie van
|
||||
`terminal_beschikbaar()` gebruikte `{ : </dev/tty; }`. `:` is een *special
|
||||
builtin*, en een mislukte redirect daarop beëindigt volgens POSIX de hele shell
|
||||
— exit 2, zonder melding, nog vóór de eerste stap. Dat brak elke installatie
|
||||
zonder terminal. De openpoging staat nu in een subshell.
|
||||
|
||||
# v0.10.00-beta — Server Up draait niet meer als root
|
||||
|
||||
Er stond `user: "0:0"` in `docker-compose.yml` en nergens waarom. Dat is nu een
|
||||
|
|
|
|||
2
VERSION
2
VERSION
|
|
@ -1 +1 @@
|
|||
0.10.00-beta
|
||||
0.10.10-beta
|
||||
|
|
|
|||
|
|
@ -62,6 +62,17 @@ schrijven én `docker` aanroepen, dan blijft alles onder je eigen account.
|
|||
--dry-run Alleen tonen wat er zou gebeuren
|
||||
```
|
||||
|
||||
Het script vraagt ook wanneer je het met `curl … | sh` draait: het praat met je
|
||||
terminal, niet met stdin. Wil je écht niets gevraagd krijgen, gebruik dan
|
||||
`--yes`.
|
||||
|
||||
Duurt de eerste start langer dan anderhalve minuut — een trage schijf, een
|
||||
zwakke machine — zet dan het aantal pogingen hoger:
|
||||
|
||||
```bash
|
||||
SU_WACHT_POGINGEN=120 sh install.sh
|
||||
```
|
||||
|
||||
### Voorbeelden
|
||||
|
||||
```bash
|
||||
|
|
|
|||
100
install.sh
100
install.sh
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
set -eu
|
||||
|
||||
SCRIPT_VERSIE="1.1"
|
||||
SCRIPT_VERSIE="1.2"
|
||||
GIT_HOST="git.ramonbesselink.nl"
|
||||
GIT_PAD="bes-r/server-up"
|
||||
BRANCH="main"
|
||||
|
|
@ -38,6 +38,9 @@ SU_UID=""
|
|||
SU_GID=""
|
||||
SU_NAAM=""
|
||||
BASE_DIR="${BASE_DIR:-}"
|
||||
# Heeft de server na het starten daadwerkelijk geantwoord? Bepaalt het slot en
|
||||
# de exitcode; bij --dry-run is er niets om op te wachten.
|
||||
GEREED=1
|
||||
|
||||
# ── Uitvoer ──────────────────────────────────────────────────────────────────
|
||||
# Kleuren alleen als we naar een terminal schrijven; in een pipe of logbestand
|
||||
|
|
@ -71,10 +74,28 @@ doe() {
|
|||
fi
|
||||
}
|
||||
|
||||
# Is er een terminal om iets aan te vragen? Bewust /dev/tty en niet stdin: bij
|
||||
# `curl … | sh` — de manier die de README noemt — is stdin de pipe, terwijl de
|
||||
# terminal gewoon bereikbaar is. Op stdin testen betekende dat élke vraag
|
||||
# ongesteld bleef en zichzelf met "ja" beantwoordde: Docker werd van
|
||||
# get.docker.com gehaald zonder dat het gevraagd was, en --uninstall brak je
|
||||
# installatie af zonder bevestiging.
|
||||
#
|
||||
# Bestaan is niet genoeg: in een container zonder terminal bestaat /dev/tty wel
|
||||
# maar levert openen "No such device or address".
|
||||
# De openpoging staat in een subshell, niet tussen accolades: ':' is een
|
||||
# special builtin, en een mislukte redirect daarop beëindigt volgens POSIX de
|
||||
# hele shell. In een subshell sneuvelt alleen die subshell.
|
||||
terminal_beschikbaar() {
|
||||
[ -e /dev/tty ] || return 1
|
||||
( : </dev/tty ) 2>/dev/null || return 1
|
||||
return 0
|
||||
}
|
||||
|
||||
vraag() {
|
||||
# vraag "Vraag?" -> 0 bij ja. Met --yes of zonder terminal: altijd ja.
|
||||
[ "$JA" -eq 1 ] && return 0
|
||||
[ -t 0 ] || return 0
|
||||
terminal_beschikbaar || return 0
|
||||
printf ' %s [J/n] ' "$1"
|
||||
read -r antwoord </dev/tty || return 0
|
||||
case "$antwoord" in [nN]*) return 1 ;; *) return 0 ;; esac
|
||||
|
|
@ -161,6 +182,20 @@ geldig_bind() {
|
|||
}
|
||||
geldig_bind "$BIND" || fout "Ongeldig bind-adres: $BIND (verwacht een IP-adres, bijvoorbeeld 127.0.0.1 of 0.0.0.0)"
|
||||
|
||||
# Waar bereiken wíj de server na het starten? Compose publiceert op $BIND, dus
|
||||
# met een specifiek adres luistert er niets op 127.0.0.1. Daar toch naartoe
|
||||
# vragen leverde "reageerde niet binnen anderhalve minuut" en een overgeslagen
|
||||
# beheerdersaccount op, terwijl alles gewoon draaide — precies de installatie
|
||||
# die daarna zonder account open staat.
|
||||
probe_adres() {
|
||||
case "$BIND" in
|
||||
''|0.0.0.0) printf '127.0.0.1' ;;
|
||||
::|'[::]') printf '[::1]' ;;
|
||||
*:*) printf '[%s]' "$BIND" ;; # IPv6 hoort tussen blokhaken
|
||||
*) printf '%s' "$BIND" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# ── Rechten ──────────────────────────────────────────────────────────────────
|
||||
# Alleen sudo gebruiken waar het echt nodig is: kan de gebruiker zelf al in de
|
||||
# doelmap schrijven en docker aanroepen, dan blijft alles onder zijn eigen account.
|
||||
|
|
@ -286,7 +321,7 @@ kies_bind() {
|
|||
[ "$BIND_EXPLICIET" -eq 1 ] && return 0
|
||||
[ "$JA" -eq 1 ] && return 0
|
||||
[ "$DROOG" -eq 1 ] && return 0
|
||||
[ -e /dev/tty ] || return 0
|
||||
terminal_beschikbaar || return 0
|
||||
|
||||
# Installeer je opnieuw over een bestaande map, dan is je huidige keuze het
|
||||
# uitgangspunt — anders zet enter je server ongemerkt terug op loopback.
|
||||
|
|
@ -420,7 +455,7 @@ kies_gebruiker() {
|
|||
# zonder dit zou een bestaande installatie elke keer opnieuw vragen.
|
||||
lees_env_terug "$DOEL/.env"
|
||||
[ -n "$SU_UID" ] && return 0
|
||||
if [ "$JA" -eq 1 ] || [ ! -e /dev/tty ]; then
|
||||
if [ "$JA" -eq 1 ] || ! terminal_beschikbaar; then
|
||||
zet_gebruiker serverup
|
||||
return 0
|
||||
fi
|
||||
|
|
@ -600,14 +635,21 @@ start() {
|
|||
|
||||
wacht_op_gereed() {
|
||||
[ "$DROOG" -eq 1 ] && return 0
|
||||
# Aantal pogingen is instelbaar: op een trage machine duurt de eerste start
|
||||
# langer dan anderhalve minuut, en de tests willen niet zo lang wachten.
|
||||
pogingen="${SU_WACHT_POGINGEN:-45}"
|
||||
basis="http://$(probe_adres):${POORT}"
|
||||
stap "Wachten tot Server Up reageert"
|
||||
printf ' '
|
||||
i=0
|
||||
while [ "$i" -lt 45 ]; do
|
||||
if curl -fsS "http://127.0.0.1:${POORT}/healthz" >/dev/null 2>&1; then
|
||||
# Zonder tijdslimiet blijft curl hangen op een adres waar niets naartoe
|
||||
# routeert, en betekent het aantal pogingen niets meer.
|
||||
tijden="--connect-timeout 2 --max-time 5"
|
||||
while [ "$i" -lt "$pogingen" ]; do
|
||||
if curl -fsS $tijden "${basis}/healthz" >/dev/null 2>&1; then
|
||||
# Spatie na de dubbele punt toestaan: of json compact is,
|
||||
# hangt af van de Flask-versie.
|
||||
versie="$(curl -fsS "http://127.0.0.1:${POORT}/healthz" 2>/dev/null \
|
||||
versie="$(curl -fsS $tijden "${basis}/healthz" 2>/dev/null \
|
||||
| sed -n 's/.*"version" *: *"\([^"]*\)".*/\1/p')"
|
||||
printf '\n'
|
||||
goed "Server Up${versie:+ }${versie:-} draait"
|
||||
|
|
@ -619,7 +661,7 @@ wacht_op_gereed() {
|
|||
sleep 2
|
||||
done
|
||||
printf '\n'
|
||||
waarschuw "Server Up reageerde niet binnen anderhalve minuut."
|
||||
waarschuw "Server Up reageerde niet op ${basis}."
|
||||
log "Bekijk de logs met: $SUDO docker compose -f $DOEL/docker-compose.yml logs --tail=50"
|
||||
return 1
|
||||
}
|
||||
|
|
@ -681,7 +723,7 @@ bepaal_wachtwoord() {
|
|||
BEHEERDER_WW="$SU_ADMIN_PASSWORD"
|
||||
return 0
|
||||
fi
|
||||
if [ "$JA" -eq 0 ] && [ -e /dev/tty ]; then
|
||||
if [ "$JA" -eq 0 ] && terminal_beschikbaar; then
|
||||
vraag_wachtwoord && return 0
|
||||
fi
|
||||
BEHEERDER_WW="$(genereer_wachtwoord)"
|
||||
|
|
@ -696,7 +738,7 @@ vraag_beheerder() {
|
|||
[ -n "$BEHEERDER" ] && return 0
|
||||
[ "$JA" -eq 1 ] && return 0
|
||||
[ "$DROOG" -eq 1 ] && return 0
|
||||
[ -e /dev/tty ] || return 0
|
||||
terminal_beschikbaar || return 0
|
||||
|
||||
stap "Beheerdersaccount"
|
||||
if ! vraag "Nu meteen een beheerdersaccount aanmaken?"; then
|
||||
|
|
@ -740,9 +782,10 @@ maak_beheerder() {
|
|||
code="$(printf '{"username":"%s","password":"%s"}' \
|
||||
"$(json_tekst "$BEHEERDER")" "$(json_tekst "$BEHEERDER_WW")" \
|
||||
| curl -sS -o "$antwoord" -w '%{http_code}' \
|
||||
--connect-timeout 5 --max-time 20 \
|
||||
-X POST -H 'Content-Type: application/json' \
|
||||
--data-binary @- \
|
||||
"http://127.0.0.1:${POORT}/api/auth/setup" 2>/dev/null || true)"
|
||||
"http://$(probe_adres):${POORT}/api/auth/setup" 2>/dev/null || true)"
|
||||
# Bij een mislukte verbinding schrijft curl zelf al "000"; kan curl helemaal
|
||||
# niet draaien, dan blijft het leeg. Beide gevallen zijn hetzelfde verhaal.
|
||||
case "$code" in ''|*[!0-9]*) code="000" ;; esac
|
||||
|
|
@ -775,9 +818,19 @@ afsluiting() {
|
|||
fi
|
||||
|
||||
printf '\n%s────────────────────────────────────────────────────────%s\n' "$C_KOP" "$C_UIT"
|
||||
if [ "$GEREED" -eq 1 ]; then
|
||||
printf '%s Server Up draait op %s%s\n' "$C_OK" "$adres" "$C_UIT"
|
||||
else
|
||||
printf '%s Server Up antwoordde niet op %s%s\n' "$C_WAARSCHUW" "$adres" "$C_UIT"
|
||||
fi
|
||||
printf '%s────────────────────────────────────────────────────────%s\n\n' "$C_KOP" "$C_UIT"
|
||||
|
||||
if [ "$GEREED" -eq 0 ]; then
|
||||
printf ' De container is aangemaakt, maar reageerde nog niet. Kijk wat\n'
|
||||
printf ' er aan de hand is met:\n'
|
||||
printf ' %s docker compose -f %s/docker-compose.yml logs --tail=50\n\n' "${SUDO:-}" "$DOEL"
|
||||
fi
|
||||
|
||||
if [ -n "$BEHEERDER" ]; then
|
||||
printf ' %s✔%s Inloggen als: %s%s%s\n' "$C_OK" "$C_UIT" "$C_KOP" "$BEHEERDER" "$C_UIT"
|
||||
if [ "$WW_GEGENEREERD" -eq 1 ]; then
|
||||
|
|
@ -797,10 +850,12 @@ afsluiting() {
|
|||
printf ' 2. sed -i "s/^BIND=.*/BIND=0.0.0.0/" %s/.env\n' "$DOEL"
|
||||
printf ' 3. %s docker compose -f %s/docker-compose.yml up -d\n\n' "${SUDO:-}" "$DOEL"
|
||||
else
|
||||
printf ' %sDe interface staat open op je netwerk. Server Up beheert%s\n' "$C_WAARSCHUW" "$C_UIT"
|
||||
printf ' Docker als root, dus zet er een reverse proxy met TLS voor.\n\n'
|
||||
printf ' %sDe interface staat open op je netwerk.%s Server Up beheert de\n' "$C_WAARSCHUW" "$C_UIT"
|
||||
printf ' Docker-daemon, dus wie erbij kan, kan alles op deze server.\n'
|
||||
printf ' Zet er een reverse proxy met TLS voor.\n\n'
|
||||
fi
|
||||
|
||||
printf ' Draait als: %s\n' "${SU_NAAM:-root}"
|
||||
printf ' Bijwerken: sh %s/install.sh --update\n' "$DOEL"
|
||||
printf ' Logs: %s docker compose -f %s/docker-compose.yml logs -f\n' "${SUDO:-}" "$DOEL"
|
||||
printf ' Documentatie: %s/README.md\n\n' "$DOEL"
|
||||
|
|
@ -854,9 +909,19 @@ case "$ACTIE" in
|
|||
schrijf_env
|
||||
zet_mappen_klaar
|
||||
start
|
||||
wacht_op_gereed || true
|
||||
# Niet wegkijken als hij niet opkomt: "Bijgewerkt." bij een kapotte
|
||||
# update zag er precies zo uit als een geslaagde, en een script dat dit
|
||||
# aanroept zag exitcode 0.
|
||||
if wacht_op_gereed; then
|
||||
printf '\n'
|
||||
goed "Bijgewerkt."
|
||||
else
|
||||
printf '\n'
|
||||
log "Terug naar de vorige versie kan met:"
|
||||
log " cd $DOEL && git log --oneline -5 # kies een eerdere versie"
|
||||
log " $SUDO docker compose -f $DOEL/docker-compose.yml up -d --build"
|
||||
fout "Bijwerken mislukt: de nieuwe versie kwam niet omhoog."
|
||||
fi
|
||||
;;
|
||||
create-admin)
|
||||
# Losse actie voor een installatie die al draait: handig als het
|
||||
|
|
@ -865,7 +930,7 @@ case "$ACTIE" in
|
|||
# en één verzoek naar de draaiende server — dus geen bepaal_rechten.
|
||||
lees_env_terug "$DOEL/.env"
|
||||
if [ -z "$BEHEERDER" ]; then
|
||||
if [ -e /dev/tty ] && [ "$JA" -eq 0 ]; then
|
||||
if terminal_beschikbaar && [ "$JA" -eq 0 ]; then
|
||||
printf '\n Gebruikersnaam: '
|
||||
read -r naam </dev/tty || naam=""
|
||||
BEHEERDER="$(printf '%s' "$naam" | tr -d '[:space:]')"
|
||||
|
|
@ -889,8 +954,11 @@ case "$ACTIE" in
|
|||
schrijf_env
|
||||
zet_mappen_klaar
|
||||
start
|
||||
wacht_op_gereed || true
|
||||
# Hier wél doorgaan: de aanwijzingen aan het eind zijn juist dán nuttig.
|
||||
# Maar het slot mag niet doen alsof alles goed ging.
|
||||
if wacht_op_gereed; then GEREED=1; else GEREED=0; fi
|
||||
maak_beheerder
|
||||
afsluiting
|
||||
[ "$GEREED" -eq 1 ] || exit 1
|
||||
;;
|
||||
esac
|
||||
|
|
|
|||
|
|
@ -614,3 +614,143 @@ def test_appdata_wordt_niet_van_eigenaar_veranderd():
|
|||
continue
|
||||
if "chown" in kaal:
|
||||
assert "appdata" not in kaal, f"appdata wordt gechownd: {kaal}"
|
||||
|
||||
|
||||
# ── Waar controleert het script of de server draait? ─────────────────────────
|
||||
# Compose publiceert op $BIND. Het script vroeg altijd 127.0.0.1, dus met een
|
||||
# eigen bind-adres meldde het "reageerde niet" en sloeg het het
|
||||
# beheerdersaccount over — terwijl alles gewoon draaide. Dat laat je installatie
|
||||
# zonder account open staan, precies waar het script voor waarschuwt.
|
||||
|
||||
@pytest.mark.parametrize("bind,verwacht", [
|
||||
("127.0.0.1", "127.0.0.1"),
|
||||
("0.0.0.0", "127.0.0.1"), # alle interfaces: loopback voldoet
|
||||
("10.0.20.5", "10.0.20.5"), # specifiek adres: dáár moet je zijn
|
||||
("::", "[::1]"),
|
||||
("2001:db8::1", "[2001:db8::1]"), # IPv6 hoort tussen blokhaken in een URL
|
||||
])
|
||||
def test_het_controleadres_volgt_het_bind_adres(bind, verwacht, tmp_path):
|
||||
uit = _sh(f'BIND="{bind}"\nprobe_adres\nprintf "\\n"\n', tmp_path)
|
||||
assert uit.strip().splitlines()[-1] == verwacht, uit
|
||||
|
||||
|
||||
def _sh(fragment, tmp_path):
|
||||
"""Laadt install.sh en draait een fragment; geen terminal in het spel."""
|
||||
script = tmp_path / "frag.sh"
|
||||
script.write_text(f"set --\nSU_INSTALL_ALLEEN_FUNCTIES=1 . {SCRIPT}\n{fragment}\n")
|
||||
r = subprocess.run(["sh", str(script)], capture_output=True, text=True,
|
||||
timeout=60, stdin=subprocess.DEVNULL)
|
||||
return r.stdout + r.stderr
|
||||
|
||||
|
||||
def _server(poort_uit, pad="/healthz", inhoud=b'{"version":"9.9.9"}'):
|
||||
"""Een minimale HTTP-server op 127.0.0.1 die één pad kent."""
|
||||
import http.server
|
||||
import threading
|
||||
|
||||
class H(http.server.BaseHTTPRequestHandler):
|
||||
def do_GET(self):
|
||||
if self.path == pad:
|
||||
self.send_response(200)
|
||||
self.send_header("Content-Type", "application/json")
|
||||
self.send_header("Content-Length", str(len(inhoud)))
|
||||
self.end_headers()
|
||||
self.wfile.write(inhoud)
|
||||
else:
|
||||
self.send_error(404)
|
||||
|
||||
def log_message(self, *a):
|
||||
pass
|
||||
|
||||
srv = http.server.HTTPServer(("127.0.0.1", 0), H)
|
||||
poort_uit.append(srv.server_address[1])
|
||||
threading.Thread(target=srv.serve_forever, daemon=True).start()
|
||||
return srv
|
||||
|
||||
|
||||
def test_wachten_slaagt_zodra_de_server_antwoordt(tmp_path):
|
||||
poort = []
|
||||
srv = _server(poort)
|
||||
try:
|
||||
uit = _sh(f'DROOG=0; BIND="127.0.0.1"; POORT={poort[0]}; DOEL="{tmp_path}"\n'
|
||||
'SU_WACHT_POGINGEN=3 wacht_op_gereed && echo "UITKOMST=gereed"\n',
|
||||
tmp_path)
|
||||
finally:
|
||||
srv.shutdown()
|
||||
assert "UITKOMST=gereed" in uit, uit
|
||||
assert "9.9.9" in uit, "de versie uit /healthz wordt niet getoond"
|
||||
|
||||
|
||||
def test_wachten_kijkt_naar_het_ingestelde_adres_niet_naar_loopback(tmp_path):
|
||||
"""De server luistert op 127.0.0.1, maar we doen alsof BIND iets anders is.
|
||||
Vroeg het script tóch 127.0.0.1, dan zou dit ten onrechte slagen."""
|
||||
poort = []
|
||||
srv = _server(poort)
|
||||
try:
|
||||
uit = _sh(f'DROOG=0; BIND="10.255.255.1"; POORT={poort[0]}; DOEL="{tmp_path}"\n'
|
||||
'SU_WACHT_POGINGEN=1 wacht_op_gereed || echo "UITKOMST=niet-gereed"\n',
|
||||
tmp_path)
|
||||
finally:
|
||||
srv.shutdown()
|
||||
assert "UITKOMST=niet-gereed" in uit, uit
|
||||
assert "10.255.255.1" in uit, "de melding noemt het gevraagde adres niet"
|
||||
|
||||
|
||||
def test_wachten_faalt_als_er_niets_luistert(tmp_path):
|
||||
uit = _sh(f'DROOG=0; BIND="127.0.0.1"; POORT=1; DOEL="{tmp_path}"\n'
|
||||
'SU_WACHT_POGINGEN=1 wacht_op_gereed || echo "UITKOMST=niet-gereed"\n',
|
||||
tmp_path)
|
||||
assert "UITKOMST=niet-gereed" in uit, uit
|
||||
assert "logs --tail" in uit, "geen aanwijzing hoe je verder kijkt"
|
||||
|
||||
|
||||
def test_een_mislukte_update_meldt_zich_als_mislukt():
|
||||
"""`wacht_op_gereed || true` gevolgd door "Bijgewerkt." maakte een kapotte
|
||||
update niet te onderscheiden van een geslaagde, ook niet aan de exitcode."""
|
||||
regels = SCRIPT.read_text(encoding="utf-8").splitlines()
|
||||
for i, regel in enumerate(regels):
|
||||
if "wacht_op_gereed" not in regel or regel.strip().startswith("#"):
|
||||
continue
|
||||
assert "|| true" not in regel, \
|
||||
f"regel {i+1} negeert of de server opkwam: {regel.strip()}"
|
||||
|
||||
|
||||
# ── Vragen bij `curl | sh` ───────────────────────────────────────────────────
|
||||
# De README noemt `curl … | sh` als de manier om te installeren. Daarbij is
|
||||
# stdin de pipe, niet de terminal. `vraag()` testte op stdin en beantwoordde
|
||||
# zichzelf dus met "ja": Docker werd van get.docker.com gehaald zonder dat het
|
||||
# gevraagd was, en --uninstall brak je installatie af zonder bevestiging.
|
||||
|
||||
# `</dev/null` bootst de pipe na; /dev/tty is in deze harnas de pseudo-terminal.
|
||||
PIPE_FRAGMENT = (
|
||||
'JA=0\n'
|
||||
'if vraag "Doorgaan?" </dev/null; then echo "UITKOMST=ja"; else echo "UITKOMST=nee"; fi\n'
|
||||
)
|
||||
|
||||
|
||||
def test_de_vraag_wordt_ook_gesteld_als_stdin_geen_terminal_is(tmp_path):
|
||||
uit = _in_terminal(PIPE_FRAGMENT, "n\n", tmp_path)
|
||||
assert "Doorgaan? [J/n]" in uit, f"de vraag is niet eens gesteld: {uit}"
|
||||
assert "UITKOMST=nee" in uit, uit
|
||||
|
||||
|
||||
def test_ja_blijft_ja(tmp_path):
|
||||
uit = _in_terminal(PIPE_FRAGMENT, "\n", tmp_path)
|
||||
assert "UITKOMST=ja" in uit, uit
|
||||
|
||||
|
||||
def test_zonder_enige_terminal_gaat_hij_door(tmp_path):
|
||||
"""Geen terminal én geen stdin: dan blijft "ja" het antwoord, want anders
|
||||
kan een onbeheerde installatie nergens meer verder."""
|
||||
uit = _sh(PIPE_FRAGMENT, tmp_path)
|
||||
assert "UITKOMST=ja" in uit, uit
|
||||
|
||||
|
||||
def test_zonder_terminal_valt_het_script_niet_om(tmp_path):
|
||||
"""`{ : </dev/tty; }` lijkt onschuldig, maar ':' is een special builtin en
|
||||
een mislukte redirect daarop beëindigt volgens POSIX de hele shell — exit 2,
|
||||
zonder melding, nog vóór de eerste stap."""
|
||||
uit = _sh('if terminal_beschikbaar; then echo "UITKOMST=tty"; '
|
||||
'else echo "UITKOMST=geen-tty"; fi\necho "EINDE"\n', tmp_path)
|
||||
assert "UITKOMST=geen-tty" in uit, uit
|
||||
assert "EINDE" in uit, "het script stopte halverwege"
|
||||
|
|
|
|||
Loading…
Reference in a new issue