From ed052cd62f2b5b03979ce0659600aafb04d4e729 Mon Sep 17 00:00:00 2001 From: duffyduck Date: Sun, 20 Sep 2026 15:54:01 +0200 Subject: [PATCH] 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//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) --- README.md | 84 +++++++++- README_en.md | 83 ++++++++- scripts/cmk-manage.sh | 381 +++++++++++++++++++++++++++++++++++++++--- 3 files changed, 517 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index 45a2967..cbec2df 100644 --- a/README.md +++ b/README.md @@ -605,12 +605,31 @@ Docker Hub.** Im Namensraum `checkmk` auf Docker Hub gibt es ausschliesslich: | **`enterprise` (2.0 – 2.4)** | **`registry.checkmk.com/enterprise/check-mk-enterprise`** oder Image-Tarball aus dem Kundenportal | **ja** | | `free` (historisch, bis 2.1) | `docker.io/checkmk/check-mk-free` | nein | -Ab Checkmk 2.5 wurden die Editionen umbenannt (Raw → Community, -Enterprise → Pro, Managed → Ultimate MT); diese Images liegen wieder offen auf -Docker Hub. Wer also eine **2.5 oder neuer** einsetzt, nimmt einfach `pro`. +Ab Checkmk 2.5 wurden die Editionen umbenannt; diese Images liegen wieder offen +auf Docker Hub. Wer also eine **2.5 oder neuer** einsetzt, nimmt einfach `pro`. Fuer **2.2/2.3/2.4-Enterprise** fuehrt nur der Weg ueber `registry.checkmk.com` oder den Tarball. +#### Vorsicht bei den Namen + +Die Umbenennung ist die zweite grosse Stolperfalle. **checkmk.com zeigt nur +noch die neuen Namen, die Dateien und Repositories tragen bis 2.4 aber die +alten.** Konkret für 2.3.0p9 – geprüft am Versionsarchiv: + +| Auswahl auf checkmk.com | `--edition` hier | tatsächlicher Dateiname | +|---|---|---| +| Community | `raw` | `check-mk-raw-docker-2.3.0p9.tar.gz` | +| **Pro** | **`enterprise`** | **`check-mk-enterprise-docker-2.3.0p9.tar.gz`** | +| Ultimate | `cloud` | `check-mk-cloud-docker-2.3.0p9.tar.gz` | +| Ultimate MT | `managed` | `check-mk-managed-docker-2.3.0p9.tar.gz` | + +Wer auf der Website „Pro" wählt und daraus `check-mk-pro-docker-2.3.0p9.tar.gz` +ableitet, bekommt ein **HTTP 404** – diese Datei gibt es für 2.3 nicht. + +Das Skript nimmt einem das ab: es liest den echten Dateinamen aus dem +Versionsarchiv und probiert zusätzlich beide Namensvarianten durch. In der +Oberfläche steht in der Editionsauswahl jeweils beides. + > Frei herunterladbar heisst nicht lizenzfrei – der Lizenzschluessel wird > anschliessend in Checkmk selbst hinterlegt. @@ -753,10 +772,63 @@ In der ncurses-Oberfläche ist der Test an zwei Stellen erreichbar: Nach dem Ändern eines Zugangsdaten-Feldes fragt das Menü ausserdem von sich aus, ob gleich geprüft werden soll. -### 8.5 Image holen – drei Wege +### 8.5 Verfügbare Versionen auflisten + +Statt Versionsnummern zu raten: + +```bash +./scripts/cmk-manage.sh image versions --edition enterprise --filter 2.3.0p +``` + +Abgefragt werden bis zu drei Quellen: + +| Quelle | `--source` | Zugangsdaten | +|---|---|---| +| Versionsarchiv von checkmk.com | `web` | **nein** | +| Registry (Docker Hub bzw. registry.checkmk.com) | `registry` | nur für Enterprise | +| Downloadportal (Verzeichnis-Listing) | `download` | ja | + +Ohne `--source` werden alle drei versucht – so kommt auch ohne hinterlegte +Zugangsdaten eine brauchbare Liste zustande: + +``` +Versionsarchiv https://checkmk.com/download/archive + (oeffentlich, keine Zugangsdaten noetig) + 2.3.0p50 + 2.3.0p49 + 2.3.0p48 + ... + +Uebernehmen + aus der Registry : ./scripts/cmk-manage.sh image pull --edition enterprise --version + als Tarball : ./scripts/cmk-manage.sh image download --edition enterprise --version + nur eintragen : ./scripts/cmk-manage.sh config set CMK_VERSION +``` + +Weitere Optionen: `--limit N` (Vorgabe 25), `--all`, `--filter TEXT` und +`--bare` für die nackte Liste ohne Rahmen – praktisch zum Weiterverarbeiten: + +```bash +./scripts/cmk-manage.sh image versions --source web --filter 2.3.0p --bare | head -1 +``` + +In der Oberfläche gibt es den Punkt **image → „Verfügbare Versionen +auflisten"**; beim Holen eines Images muss die Version ohnehin nicht mehr +abgetippt werden – dort erscheint eine Auswahlliste. + +### 8.6 Image holen – drei Wege **a) Aus einer Registry (empfohlen)** +Für die Enterprise-Edition entspricht das genau diesen beiden Schritten – das +Skript erledigt sie in einem Aufruf und trägt das Ergebnis in die `.env` ein: + +```bash +podman login registry.checkmk.com # bzw. docker login +podman pull registry.checkmk.com/enterprise/check-mk-enterprise:2.3.0p9 +``` + + ```bash # frei verfuegbar, ohne Anmeldung sudo ./scripts/cmk-manage.sh image pull --edition raw --version 2.3.0-latest @@ -804,7 +876,7 @@ ihn als `CMK_IMAGE` in die `.env` ein. Danach: sudo ./scripts/cmk-manage.sh up ``` -### 8.6 Nachsehen, was gilt +### 8.7 Nachsehen, was gilt ```bash ./scripts/cmk-manage.sh image status # konfiguriertes + lokale Images @@ -1370,7 +1442,7 @@ Eine Dateiauswahl mit Verzeichnisnavigation ist eingebaut. | `job list\|add\|set\|del\|run\|auto` | geplante Backups (eigene Zielpfade je Job) | | `restore …` | Backup zurückspielen | | `import …` | Migrations-Bundle einspielen | -| `image status\|list\|pull\|download\|load\|use` | Checkmk-Image beschaffen und auswaehlen | +| `image status\|list\|versions\|test\|pull\|download\|load\|use` | Checkmk-Image beschaffen und auswaehlen | | `browser [--engine …]` | Terminal-Browser im Container – Proxy Manager lokal bedienen | | `config list\|get\|set\|edit` | Einstellungen der `.env` anzeigen und ändern | | `npm-port [PORT]` | Port der Proxy-Manager-Oberfläche setzen/anzeigen | diff --git a/README_en.md b/README_en.md index 16216b6..91fccc8 100644 --- a/README_en.md +++ b/README_en.md @@ -608,12 +608,32 @@ Hub.** The `checkmk` namespace on Docker Hub contains only: | **`enterprise` (2.0 – 2.4)** | **`registry.checkmk.com/enterprise/check-mk-enterprise`** or an image tarball from the customer portal | **yes** | | `free` (historic, up to 2.1) | `docker.io/checkmk/check-mk-free` | no | -With Checkmk 2.5 the editions were renamed (Raw → Community, -Enterprise → Pro, Managed → Ultimate MT); those images are publicly available +With Checkmk 2.5 the editions were renamed; those images are publicly available on Docker Hub again. So if you run **2.5 or newer**, simply use `pro`. For **2.2/2.3/2.4 Enterprise** the only routes are `registry.checkmk.com` or the tarball. +#### Beware of the names + +The rename is the second big pitfall. **checkmk.com only shows the new names, +while files and repositories keep the old ones up to 2.4.** For 2.3.0p9 +specifically – verified against the version archive: + +| Choice on checkmk.com | `--edition` here | actual file name | +|---|---|---| +| Community | `raw` | `check-mk-raw-docker-2.3.0p9.tar.gz` | +| **Pro** | **`enterprise`** | **`check-mk-enterprise-docker-2.3.0p9.tar.gz`** | +| Ultimate | `cloud` | `check-mk-cloud-docker-2.3.0p9.tar.gz` | +| Ultimate MT | `managed` | `check-mk-managed-docker-2.3.0p9.tar.gz` | + +Picking "Pro" on the website and deriving +`check-mk-pro-docker-2.3.0p9.tar.gz` from it yields an **HTTP 404** – that file +does not exist for 2.3. + +The script takes care of this: it reads the real file name from the version +archive and additionally tries both naming variants. In the interface the +edition list shows both names. + > Freely downloadable does not mean licence-free – the licence key is entered > inside Checkmk afterwards. @@ -758,10 +778,63 @@ In the ncurses interface the test can be reached from two places: After changing a credential field the menu also offers to run the test straight away. -### 8.5 Fetching the image – three ways +### 8.5 Listing the available versions + +Instead of guessing version numbers: + +```bash +./scripts/cmk-manage.sh image versions --edition enterprise --filter 2.3.0p +``` + +Up to three sources are queried: + +| Source | `--source` | Credentials | +|---|---|---| +| version archive on checkmk.com | `web` | **no** | +| registry (Docker Hub or registry.checkmk.com) | `registry` | only for Enterprise | +| download portal (directory listing) | `download` | yes | + +Without `--source` all three are tried – so even without stored credentials you +get a usable list: + +``` +Versionsarchiv https://checkmk.com/download/archive + (oeffentlich, keine Zugangsdaten noetig) + 2.3.0p50 + 2.3.0p49 + 2.3.0p48 + ... + +Uebernehmen + aus der Registry : ./scripts/cmk-manage.sh image pull --edition enterprise --version + als Tarball : ./scripts/cmk-manage.sh image download --edition enterprise --version + nur eintragen : ./scripts/cmk-manage.sh config set CMK_VERSION +``` + +Further options: `--limit N` (default 25), `--all`, `--filter TEXT` and +`--bare` for the plain list without any framing – handy for scripting: + +```bash +./scripts/cmk-manage.sh image versions --source web --filter 2.3.0p --bare | head -1 +``` + +In the interface there is **image → "Verfügbare Versionen auflisten"**; and +when fetching an image the version no longer has to be typed at all – a +selection list appears instead. + +### 8.6 Fetching the image – three ways **a) From a registry (recommended)** +For the Enterprise edition this is exactly the following two steps – the script +performs them in one call and writes the result into `.env`: + +```bash +podman login registry.checkmk.com # or docker login +podman pull registry.checkmk.com/enterprise/check-mk-enterprise:2.3.0p9 +``` + + ```bash # freely available, no login sudo ./scripts/cmk-manage.sh image pull --edition raw --version 2.3.0-latest @@ -809,7 +882,7 @@ typically `localhost/checkmk/check-mk-enterprise:2.3.0p23`) and writes it to sudo ./scripts/cmk-manage.sh up ``` -### 8.6 Checking what is in effect +### 8.7 Checking what is in effect ```bash ./scripts/cmk-manage.sh image status # configured image + local images @@ -1378,7 +1451,7 @@ A file chooser with directory navigation is built in. | `job list\|add\|set\|del\|run\|auto` | scheduled backups (own target path per job) | | `restore …` | restore a backup | | `import …` | import a migration bundle | -| `image status\|list\|pull\|download\|load\|use` | obtain and select the Checkmk image | +| `image status\|list\|versions\|test\|pull\|download\|load\|use` | obtain and select the Checkmk image | | `browser [--engine …]` | terminal browser in a container – operate the Proxy Manager locally | | `config list\|get\|set\|edit` | show and change settings in `.env` | | `npm-port [PORT]` | set/show the port of the Proxy Manager interface | diff --git a/scripts/cmk-manage.sh b/scripts/cmk-manage.sh index 5aaf2b7..35dba6e 100755 --- a/scripts/cmk-manage.sh +++ b/scripts/cmk-manage.sh @@ -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//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 < + als Tarball : $SELF image download --edition $edition --version + nur eintragen : $SELF config set CMK_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:-} 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'"