Versionen auflisten, echtes Dateinamensschema, Editionsnamen entwirrt

Anlass war der Hinweis auf die tatsaechliche Download-URL. Am echten
Server nachgemessen:
    check-mk-raw-docker-2.3.0p9.tar.gz         -> 200 (frei)
    check-mk-enterprise-docker-2.3.0p9.tar.gz  -> 401 (geschuetzt)
    check-mk-pro-docker-2.3.0p9.tar.gz         -> 404
    check-mk-raw-2.3.0p9.docker.tar.gz         -> 404
Das bisher zuerst probierte Schema war also schlicht falsch.

Editionsnamen: checkmk.com zeigt nur noch Community/Pro/Ultimate/
Ultimate MT, Dateien und Repositories tragen bis 2.4 weiter
raw/enterprise/cloud/managed. Wer von "Pro" auf check-mk-pro-... schliesst,
bekommt 404. Die Editionsauswahl in der Oberflaeche nennt jetzt beide
Namen, die README hat eine Zuordnungstabelle, und intern werden beide
Varianten durchprobiert.

Neu: "image versions" listet verfuegbare Versionen aus bis zu drei
Quellen - Versionsarchiv von checkmk.com (oeffentlich, ohne
Zugangsdaten), Registry ueber /v2/<repo>/tags/list und das
Verzeichnis-Listing des Downloadportals. Mit --filter, --limit, --all,
--source und --bare fuer die nackte Liste zum Weiterverarbeiten. Am
Ende stehen die fertigen Kommandos zum Uebernehmen.

Das Archiv liefert ausserdem den EXAKTEN Dateinamen je Version und
Edition (data-versions im HTML). Der wird jetzt als erster Kandidat
verwendet, statt ihn zu raten - geprueft fuer raw, enterprise, cloud
und managed auf 2.3.0p9, der erste Kandidat fuer raw liefert am Server
HTTP 200.

In der Oberflaeche: neuer Punkt "Verfuegbare Versionen auflisten", und
beim Holen eines Images muss die Version nicht mehr abgetippt werden -
es erscheint eine Auswahlliste aus dem Archiv.

Gegen Docker Hub verifiziert: 2393 Tags korrekt eingelesen, Filter und
Sortierung stimmen.

Dokumentiert als Abschnitt 8.5 in beiden Sprachfassungen.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-20 15:54:01 +02:00
co-authored by Claude Opus 5
parent 2f00f81179
commit ed052cd62f
3 changed files with 517 additions and 31 deletions
+361 -20
View File
@@ -107,6 +107,15 @@ KOMMANDOS - Backup / Restore / Migration
KOMMANDOS - Checkmk-Image beschaffen
image status konfiguriertes und lokal vorhandene Images anzeigen
image list lokal vorhandene Checkmk-Images
image versions [Opt.] verfuegbare Versionen auflisten (zum Kopieren)
--edition E Edition (Vorgabe: CMK_EDITION)
--source registry|download|web|all Quelle (Vorgabe all)
web = oeffentliches Versionsarchiv von checkmk.com,
funktioniert ohne Zugangsdaten
--filter TEXT nur Versionen, die TEXT enthalten, z.B. 2.3.0
--limit N hoechstens N Eintraege (Vorgabe 25), --all fuer alle
--user U --password P statt der Werte aus der .env
--bare nur die nackte Liste, ohne Rahmen
image test [Opt.] Zugangsdaten pruefen, ohne etwas herunterzuladen
--edition E Edition, deren Repository geprueft wird
--version V Version fuer die Pruefung des Downloadportals
@@ -457,6 +466,94 @@ image_fetch_url() {
fi
}
# ---------------------------------------------------------------------
# Versionsarchiv von checkmk.com
#
# https://checkmk.com/download/archive ist serverseitig gerendert und
# braucht KEINE Zugangsdaten. Je Version steht dort
# data-handle="2.3.0p9" data-versions="{...}"
# und im JSON die echten Dateinamen je Edition. Daran haengt auch die
# Aufloesung der Verwirrung um die Editionsnamen: die Website benennt
# 2.3.0p9 als "pro", die Datei heisst weiterhin
# check-mk-enterprise-docker-2.3.0p9.tar.gz
# ---------------------------------------------------------------------
ARCHIVE_CACHE=""
archive_fetch() { # Seite einmal je Aufruf holen, Pfad auf stdout
if [ -n "$ARCHIVE_CACHE" ] && [ -s "$ARCHIVE_CACHE" ]; then
printf '%s\n' "$ARCHIVE_CACHE"; return 0
fi
command -v curl >/dev/null 2>&1 || return 1
local f; f="$(mktemp)"
if curl -sS -L --max-time 60 "${CMK_ARCHIVE_URL:-https://checkmk.com/download/archive}" -o "$f" 2>/dev/null \
&& [ -s "$f" ]; then
ARCHIVE_CACHE="$f"; printf '%s\n' "$f"; return 0
fi
rm -f "$f"; return 1
}
archive_versions() { # alle im Archiv gelisteten Versionen
local f; f="$(archive_fetch)" || return 1
grep -oE 'data-handle="[0-9]+\.[0-9]+\.[0-9]+[a-z0-9.]*"' "$f" \
| sed -E 's/data-handle="([^"]*)"/\1/' | sort -u
}
# Exakten Dateinamen des Docker-Tarballs ermitteln
archive_docker_file() { # edition version -> Dateiname auf stdout
local edition="$1" version="$2"
local f; f="$(archive_fetch)" || return 1
# Abschnitt dieser Version herausschneiden und die Docker-Dateinamen lesen
local names
names="$(grep -oE "data-handle=\"$version\"[^>]*" "$f" \
| grep -oE "check-mk-[a-z]+-docker-${version}\.tar\.gz" | sort -u)"
[ -n "$names" ] || return 1
local ed
for ed in $(edition_aliases "$edition"); do
if printf '%s\n' "$names" | grep -qx "check-mk-${ed}-docker-${version}.tar.gz"; then
printf 'check-mk-%s-docker-%s.tar.gz\n' "$ed" "$version"; return 0
fi
done
return 1
}
# Dateinamen der Image-Tarballs im Downloadportal.
# Bestaetigt am echten Server:
# .../checkmk/2.3.0p9/check-mk-raw-docker-2.3.0p9.tar.gz -> 200
# .../checkmk/2.3.0p9/check-mk-enterprise-docker-2.3.0p9.tar.gz -> 401 (geschuetzt)
# .../checkmk/2.3.0p9/check-mk-raw-2.3.0p9.docker.tar.gz -> 404
# Zusaetzlich die Editionsnamen ab 2.5 mitprobieren, damit derselbe
# Aufruf auch fuer neuere Versionen funktioniert.
edition_aliases() {
case "$1" in
enterprise) printf '%s\n' enterprise pro ;;
pro) printf '%s\n' pro enterprise ;;
raw) printf '%s\n' raw community ;;
community) printf '%s\n' community raw ;;
managed) printf '%s\n' managed ultimatemt ;;
ultimatemt) printf '%s\n' ultimatemt managed ;;
*) printf '%s\n' "$1" ;;
esac
}
download_url_candidates() { # edition version -> URLs, beste zuerst
local edition="$1" version="$2" ed
local base="${CMK_DOWNLOAD_BASEURL:-https://download.checkmk.com/checkmk}"
# 1. Wahl: der im Archiv hinterlegte, echte Dateiname
local exact
if exact="$(archive_docker_file "$edition" "$version" 2>/dev/null)" && [ -n "$exact" ]; then
printf '%s/%s/%s
' "$base" "$version" "$exact"
fi
for ed in $(edition_aliases "$edition"); do
printf '%s/%s/check-mk-%s-docker-%s.tar.gz\n' "$base" "$version" "$ed" "$version"
done
# aelteres Schema, zur Sicherheit
for ed in $(edition_aliases "$edition"); do
printf '%s/%s/check-mk-%s-%s.docker.tar.gz\n' "$base" "$version" "$ed" "$version"
done
}
# ---------------------------------------------------------------------
# image pull - aus einer Registry holen
# ---------------------------------------------------------------------
@@ -564,11 +661,7 @@ image_cmd_download() {
z.B. 2.3.0p23 - '$version' funktioniert dort nicht." ;;
esac
edition_known "$edition" || die "Unbekannte Edition '$edition'."
local base="${CMK_DOWNLOAD_BASEURL:-https://download.checkmk.com/checkmk}"
local pkg; pkg="$(edition_pkgname "$edition")"
# Checkmk hat den Dateinamen ueber die Jahre geaendert - beide probieren
urls=("$base/$version/$pkg-$version.docker.tar.gz"
"$base/$version/$pkg-docker-$version.tar.gz")
mapfile -t urls < <(download_url_candidates "$edition" "$version")
fi
local target="" u
@@ -866,13 +959,11 @@ test_download_login() { # baseurl edition version user pass
fi
local netrc; netrc="$(netrc_make "$user" "$pass" "$host")"
local pkg; pkg="$(edition_pkgname "$edition")"
local -a urls=()
if [ -n "${CMK_DOWNLOAD_URL:-}" ]; then
urls=("$CMK_DOWNLOAD_URL")
elif [ -n "$version" ]; then
urls=("$base/$version/$pkg-$version.docker.tar.gz"
"$base/$version/$pkg-docker-$version.tar.gz")
mapfile -t urls < <(download_url_candidates "$edition" "$version")
else
urls=("$base/")
fi
@@ -973,6 +1064,194 @@ image_cmd_test() {
return 1
}
# ---------------------------------------------------------------------
# image versions - verfuegbare Versionen auflisten
#
# Registry : ueber den Docker-Registry-v2-Ablauf /v2/<repo>/tags/list
# Portal : ueber das Verzeichnis-Listing von download.checkmk.com
# (nur mit Zugangsdaten lesbar)
# ---------------------------------------------------------------------
# Token fuer eine Registry besorgen ("" = anonym versuchen)
registry_get_token() { # api repo user pass -> Token auf stdout
local api="$1" repo="$2" user="$3" pass="$4"
local hdrf; hdrf="$(mktemp)"
curl -sS -o /dev/null -D "$hdrf" --max-time 30 "https://$api/v2/" >/dev/null 2>&1 || true
local wa realm service
wa="$(tr -d '\r' <"$hdrf" | grep -i '^www-authenticate:' | head -n1)"
rm -f "$hdrf"
case "$wa" in
*[Bb]earer*) : ;;
*) return 0 ;; # Basic oder offen - kein Token noetig
esac
realm="$(printf '%s' "$wa" | sed -n 's/.*realm="\([^"]*\)".*/\1/p')"
service="$(printf '%s' "$wa" | sed -n 's/.*service="\([^"]*\)".*/\1/p')"
[ -n "$realm" ] || return 0
local realm_host; realm_host="$(printf '%s' "$realm" | sed -E 's|^[a-z]+://([^/]+).*|\1|')"
local url="$realm?service=$service&scope=repository:$repo:pull"
local body netrc=""
if [ -n "$user" ]; then
netrc="$(netrc_make "$user" "$pass" "$api" "$realm_host")"
body="$(curl -sS --netrc-file "$netrc" --max-time 30 "$url" 2>/dev/null || true)"
rm -f "$netrc"
else
body="$(curl -sS --max-time 30 "$url" 2>/dev/null || true)"
fi
local t
t="$(printf '%s' "$body" | sed -n 's/.*"token"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p')"
[ -n "$t" ] || t="$(printf '%s' "$body" | sed -n 's/.*"access_token"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p')"
printf '%s' "$t"
}
registry_tags() { # api repo user pass -> Tags, eine je Zeile
local api="$1" repo="$2" user="$3" pass="$4"
local token; token="$(registry_get_token "$api" "$repo" "$user" "$pass")"
local -a a=(-sS --max-time 45)
if [ -n "$token" ]; then
a+=(-H "Authorization: Bearer $token")
elif [ -n "$user" ]; then
local netrc; netrc="$(netrc_make "$user" "$pass" "$api")"
a+=(--netrc-file "$netrc")
fi
local body
body="$(curl "${a[@]}" "https://$api/v2/$repo/tags/list" 2>/dev/null || true)"
printf '%s' "$body" \
| tr ',' '\n' \
| sed -n 's/.*"tags"[[:space:]]*:[[:space:]]*\[[[:space:]]*"\([^"]*\)".*/\1/p;s/^[[:space:]]*"\([^"]*\)".*/\1/p' \
| sed 's/[]["]//g' | sed '/^$/d'
}
download_versions() { # user pass -> Versionsverzeichnisse
local user="$1" pass="$2"
local base="${CMK_DOWNLOAD_BASEURL:-https://download.checkmk.com/checkmk}"
local host; host="$(printf '%s' "$base" | sed -E 's|^[a-z]+://([^/]+).*|\1|')"
local -a a=(-sS --max-time 45 -L)
local netrc=""
if [ -n "$user" ]; then
netrc="$(netrc_make "$user" "$pass" "$host")"; a+=(--netrc-file "$netrc")
fi
local body; body="$(curl "${a[@]}" "$base/" 2>/dev/null || true)"
[ -n "$netrc" ] && rm -f "$netrc"
printf '%s' "$body" \
| grep -oE 'href="[0-9]+\.[0-9]+\.[0-9]+[a-z0-9.]*/?"' \
| sed -E 's|href="([^"/]+)/?"|\1|' | sort -u
}
image_cmd_versions() {
local edition="${CMK_EDITION:-raw}" source="all" filter="" limit=25
local ruser="${CMK_REGISTRY_USER:-}" rpass="${CMK_REGISTRY_PASSWORD:-}"
local duser="${CMK_DOWNLOAD_USER:-}" dpass="${CMK_DOWNLOAD_PASSWORD:-}"
local reg="${CMK_REGISTRY:-registry.checkmk.com}" raw=""
while [ $# -gt 0 ]; do
case "$1" in
--edition) edition="$2"; shift 2 ;;
--source) source="$2"; shift 2 ;;
--filter) filter="$2"; shift 2 ;;
--limit) limit="$2"; shift 2 ;;
--all) limit=100000; shift ;;
--registry) reg="$2"; shift 2 ;;
--user) ruser="$2"; duser="$2"; shift 2 ;;
--password) rpass="$2"; dpass="$2"; shift 2 ;;
--bare) raw=1; shift ;;
*) die "Unbekannte Option fuer 'image versions': $1" ;;
esac
done
edition_known "$edition" || die "Unbekannte Edition '$edition'.
Moeglich: raw community free cloud managed pro ultimate ultimatemt enterprise"
case "$source" in registry|download|web|both|all) : ;;
*) die "--source: registry | download | web | all" ;; esac
[ "$source" = both ] && source=all
case "$limit" in ''|*[!0-9]*) die "--limit braucht eine Zahl." ;; esac
command -v curl >/dev/null 2>&1 || die "Fuer 'image versions' wird curl benoetigt."
CMK_REGISTRY="$reg"
local full repo api
full="$(edition_repo "$edition")"
repo="${full#*/}"
api="$(registry_api_host "${full%%/*}")"
local found=0
if [ "$source" = web ] || [ "$source" = all ]; then
[ -n "$raw" ] || printf '\n%sVersionsarchiv %s%s\n' "$C_BLD" \
"${CMK_ARCHIVE_URL:-https://checkmk.com/download/archive}" "$C_RST"
[ -n "$raw" ] || printf ' %s(oeffentlich, keine Zugangsdaten noetig)%s\n' "$C_BLU" "$C_RST"
local -a wv=()
mapfile -t wv < <(archive_versions 2>/dev/null \
| { [ -n "$filter" ] && grep -F "$filter" || cat; } \
| sort -rV | head -n "$limit")
if [ ${#wv[@]} -eq 0 ]; then
[ -n "$raw" ] || test_result warn "Archiv nicht lesbar" "Netzzugang zu checkmk.com pruefen"
else
found=1
printf '%s\n' "${wv[@]}" | { [ -n "$raw" ] && cat || sed 's/^/ /'; }
fi
fi
if [ "$source" = registry ] || [ "$source" = all ]; then
[ -n "$raw" ] || printf '\n%sRegistry %s%s\n' "$C_BLD" "$full" "$C_RST"
local -a tags=()
mapfile -t tags < <(registry_tags "$api" "$repo" "$ruser" "$rpass" \
| { [ -n "$filter" ] && grep -F "$filter" || cat; } \
| sort -rV | head -n "$limit")
if [ ${#tags[@]} -eq 0 ]; then
if [ -z "$raw" ]; then
if edition_needs_login "$edition" && [ -z "$ruser" ]; then
test_result warn "keine Zugangsdaten - Registry nicht lesbar" \
"CMK_REGISTRY_USER/-PASSWORD setzen oder --user/--password angeben"
else
test_result warn "keine Tags erhalten" "Zugangsdaten und Repository pruefen"
fi
fi
else
found=1
printf '%s\n' "${tags[@]}" | { [ -n "$raw" ] && cat || sed 's/^/ /'; }
fi
fi
if [ "$source" = download ] || [ "$source" = all ]; then
[ -n "$raw" ] || printf '\n%sDownloadportal %s%s\n' "$C_BLD" \
"${CMK_DOWNLOAD_BASEURL:-https://download.checkmk.com/checkmk}" "$C_RST"
local -a vers=()
mapfile -t vers < <(download_versions "$duser" "$dpass" \
| { [ -n "$filter" ] && grep -F "$filter" || cat; } \
| sort -rV | head -n "$limit")
if [ ${#vers[@]} -eq 0 ]; then
if [ -z "$raw" ]; then
if [ -z "$duser" ]; then
test_result warn "keine Zugangsdaten - das Verzeichnis ist geschuetzt (HTTP 401)" \
"CMK_DOWNLOAD_USER/-PASSWORD setzen oder --user/--password angeben"
else
test_result warn "keine Versionen gelesen" \
"Zugangsdaten pruefen: $SELF image test --only download"
fi
fi
else
found=1
printf '%s\n' "${vers[@]}" | { [ -n "$raw" ] && cat || sed 's/^/ /'; }
fi
fi
[ -n "$raw" ] && return 0
echo
if [ "$found" = 1 ]; then
cat <<EOF
${C_BLD}Uebernehmen${C_RST}
aus der Registry : $SELF image pull --edition $edition --version <version>
als Tarball : $SELF image download --edition $edition --version <version>
nur eintragen : $SELF config set CMK_VERSION <version>
Nur die nackte Liste (zum Weiterverarbeiten): $SELF image versions --bare
EOF
else
err "Es konnte keine Versionsliste gelesen werden."
log "Zugangsdaten pruefen mit: $SELF image test"
fi
echo
[ "$found" = 1 ]
}
cmd_image() {
local sub="${1:-status}"; [ $# -gt 0 ] && shift || true
case "$sub" in
@@ -983,8 +1262,9 @@ cmd_image() {
load) image_cmd_load "$@" ;;
use|set) image_cmd_use "$@" ;;
test|check) image_cmd_test "$@" ;;
versions|tags) image_cmd_versions "$@" ;;
*) die "Unbekanntes Unterkommando 'image $sub'.
Moeglich: status | list | test | pull | download | load | use" ;;
Moeglich: status | list | versions | test | pull | download | load | use" ;;
esac
}
@@ -3043,6 +3323,7 @@ gui_image_menu() {
"Aktuell (.env): ${CMK_IMAGE:-<nicht gesetzt>}
Edition/Version: ${CMK_EDITION:-raw} / ${CMK_VERSION:-?}" \
status "Status und lokale Images anzeigen" \
versions "Verfuegbare Versionen auflisten" \
test "Zugangsdaten pruefen (Registry und Downloadportal)" \
pull "Aus Registry holen (Docker Hub / registry.checkmk.com)" \
download "Tarball vom Downloadportal holen (mit Zugangsdaten)" \
@@ -3052,6 +3333,7 @@ Edition/Version: ${CMK_EDITION:-raw} / ${CMK_VERSION:-?}" \
case "$sel" in
status) local f; f="$(mktemp)"; NO_COLOR=1 cmd_image status >"$f" 2>&1 || true
ui_text "Image-Status" "$f"; rm -f "$f" ;;
versions) gui_image_versions || true ;;
test) gui_image_test || true ;;
pull) gui_image_pull || true ;;
download) gui_image_download || true ;;
@@ -3066,15 +3348,69 @@ Edition/Version: ${CMK_EDITION:-raw} / ${CMK_VERSION:-?}" \
}
gui_image_pick_edition() {
ui_menu "Edition" "Welche Checkmk-Edition?" \
raw "Raw (frei, Docker Hub, bis 2.4)" \
community "Community (frei, Docker Hub, ab 2.5)" \
enterprise "Enterprise (NICHT auf Docker Hub - Login noetig)" \
pro "Pro (ab 2.5, Nachfolger von Enterprise)" \
cloud "Cloud (Docker Hub)" \
managed "Managed (Docker Hub, bis 2.4)" \
ultimate "Ultimate (ab 2.5)" \
ultimatemt "Ultimate Multi-Tenancy (ab 2.5)"
# Checkmk hat die Editionen umbenannt: die Website zeigt die neuen
# Namen, Dateien und Repositories tragen bis 2.4 die alten. Deshalb
# hier beide, damit die Zuordnung eindeutig ist.
ui_menu "Edition" \
"Links der Name, den dieses Werkzeug verwendet,
rechts der Name auf checkmk.com." \
raw "= Community auf der Website (frei, bis 2.4)" \
community "= Community (frei, ab 2.5)" \
enterprise "= Pro auf der Website (Login noetig, bis 2.4)" \
pro "= Pro (ab 2.5)" \
cloud "= Ultimate auf der Website (bis 2.4)" \
ultimate "= Ultimate (ab 2.5)" \
managed "= Ultimate MT auf der Website (bis 2.4)" \
ultimatemt "= Ultimate MT (ab 2.5)"
}
# Version aus dem oeffentlichen Archiv auswaehlen, statt sie abzutippen
gui_image_pick_version() { # edition [vorgabe] -> Version auf stdout
local edition="$1" cur="${2:-}"
local filt
filt="$(ui_input "Versionen filtern" \
"Nach welchem Zweig suchen? (leer = alle)
Beispiele: 2.3.0p nur Patch-Staende von 2.3.0
2.4 alles aus 2.4" "${cur%%p*}")" || return 1
local -a items=() v
while IFS= read -r v; do
[ -n "$v" ] || continue
items+=("$v" " ")
done < <(archive_versions 2>/dev/null \
| { [ -n "$filt" ] && grep -F "$filt" || cat; } | sort -rV | head -n 40)
if [ ${#items[@]} -eq 0 ]; then
ui_msg "Keine Versionen" \
"Aus dem Versionsarchiv von checkmk.com konnte nichts gelesen werden.
Entweder passt der Filter nicht, oder der Host hat keinen
Zugang zu checkmk.com. Die Version laesst sich im naechsten
Schritt auch von Hand eingeben."
ui_input "Version" "Version von Hand eingeben:" "$cur"
return
fi
items+=("__manuell__" "... von Hand eingeben ...")
local sel
sel="$(ui_menu "Version waehlen" \
"Edition: $edition
Quelle: oeffentliches Versionsarchiv von checkmk.com" "${items[@]}")" || return 1
if [ "$sel" = "__manuell__" ]; then
ui_input "Version" "Version von Hand eingeben:" "$cur"
else
printf '%s\n' "$sel"
fi
}
gui_image_versions() {
local ed
ed="$(gui_image_pick_edition)" || return 0
local f; f="$(mktemp)"
ui_info "Versionen abrufen" "Frage Versionsarchiv, Registry und Downloadportal ab ...\n\nDas kann einen Moment dauern."
NO_COLOR=1 cmd_image versions --edition "$ed" --limit 30 >"$f" 2>&1 || true
ui_text "Verfuegbare Versionen - $ed" "$f"
rm -f "$f"
}
gui_image_test() {
@@ -3096,7 +3432,7 @@ gui_image_test() {
gui_image_pull() {
local ed ver user pass
ed="$(gui_image_pick_edition)" || return 0
ver="$(ui_input "Version" "Version bzw. Tag (z.B. 2.3.0p23 oder 2.3.0-latest):" "${CMK_VERSION:-}")" || return 0
ver="$(gui_image_pick_version "$ed" "${CMK_VERSION:-}")" || return 0
[ -n "$ver" ] || return 0
local -a extra=()
if [ "$ed" = enterprise ] || [ -n "${CMK_REGISTRY_USER:-}" ]; then
@@ -3111,8 +3447,13 @@ gui_image_pull() {
gui_image_download() {
local ed ver user pass
ed="$(gui_image_pick_edition)" || return 0
ver="$(ui_input "Version" "EXAKTE Version (z.B. 2.3.0p23 - kein '-latest'):" "${CMK_VERSION:-}")" || return 0
ver="$(gui_image_pick_version "$ed" "${CMK_VERSION:-}")" || return 0
[ -n "$ver" ] || return 0
case "$ver" in
*-latest|latest|*-daily)
ui_msg "Nicht moeglich" "Fuer den Tarball-Download wird eine exakte Version gebraucht,\nz.B. 2.3.0p23 - '$ver' gibt es dort nicht."
return 0 ;;
esac
user="$(ui_input "Downloadportal" "Benutzer:" "${CMK_DOWNLOAD_USER:-}")" || return 0
pass="$(ui_password "Downloadportal" "Kennwort:")" || return 0
ui_run "Image herunterladen" bash -c "cd '$PROJECT_DIR' && '$SELF' -y image download --edition '$ed' --version '$ver' --user '$user' --password '$pass'"