diff --git a/.env.example b/.env.example index 76bd2ad..ad24036 100644 --- a/.env.example +++ b/.env.example @@ -53,6 +53,15 @@ CMK_EDITION=raw # angegeben werden (z.B. 2.3.0p23), "-latest" funktioniert dort nicht. CMK_VERSION=2.3.0-latest +# Woher soll das Image geholt werden, wenn es lokal fehlt? +# auto erst Registry, dann Downloadportal (Vorgabe) +# registry nur aus der Registry +# download nur als Tarball vom Downloadportal +# Hintergrund: Registries halten meist nur die juengsten Patchstaende +# vor. Eine aeltere Version - etwa die einer zu migrierenden Site - +# liegt dann nur noch im Downloadportal. +CMK_IMAGE_SOURCE=auto + # --- Bezugsweg 1: private Registry (Enterprise) ---------------------- # Zugangsdaten aus dem Checkmk-Kundenportal (portal.checkmk.com) CMK_REGISTRY=registry.checkmk.com diff --git a/README.md b/README.md index afe4abb..b8482f8 100644 --- a/README.md +++ b/README.md @@ -543,6 +543,7 @@ Die wichtigsten Schalter: | `CMK_RUNTIME` | leer = automatische Erkennung, sonst `docker` oder `podman` | | `CMK_IMAGE` | **das tatsaechlich verwendete Image**, immer vollqualifiziert – siehe [Kapitel 8](#8-checkmk-image-beschaffen-raw-enterprise--co) | | `CMK_EDITION`, `CMK_VERSION` | nur Vorgaben fuer den Image-Downloader | +| `CMK_IMAGE_SOURCE` | `auto`/`registry`/`download` – woher das Image geholt wird | | `CMK_REGISTRY_USER/-PASSWORD` | Anmeldung an `registry.checkmk.com` (Enterprise) | | `CMK_DOWNLOAD_USER/-PASSWORD` | Anmeldung am Checkmk-Downloadportal | | `CMK_SITE_ID` | Site, die der Container anlegt bzw. beim Start hochfährt | @@ -836,7 +837,47 @@ 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 +### 8.6 Image holen – ein Kommando, drei Wege + +Stehen Edition und Version fest, genügt: + +```bash +sudo ./scripts/cmk-manage.sh image get +``` + +Woher geholt wird, steuert **`CMK_IMAGE_SOURCE`**: + +| Wert | Wirkung | +|---|---| +| `auto` (Vorgabe) | erst die Registry, dann das Downloadportal | +| `registry` | nur aus der Registry | +| `download` | nur als Tarball vom Downloadportal | + +Einmalig abweichen: `image get --source download`. + +`auto` ist die sinnvolle Vorgabe, weil Registries nur die jüngsten Patchstände +vorhalten – eine ältere, für eine Migration nötige Version liegt dann nur noch +im Downloadportal. Der Wechsel geschieht automatisch, ohne Rückfrage. + +**Beim `up` wird automatisch geholt.** Fehlt das Image lokal und sind Edition +und Version gesetzt, beschafft `up` es zuerst über diesen Weg – sonst versucht +compose einen nackten Pull, der bei einer nur im Archiv vorhandenen Version +scheitern muss: + +``` +[ INFO ] Das Image ist lokal nicht vorhanden - hole es (auto) ... +[ INFO ] Bezugsweg 'auto': zuerst die Registry ... +[ WARN ] Aus der Registry nicht zu bekommen - versuche das Downloadportal. +``` + +Mit `up --no-fetch` bleibt das aus. + +In der Oberfläche liegt das unter **image → „Image holen"**. Dort wird nur noch +der Bezugsweg abgefragt – der eingestellte ist gekennzeichnet. Wer Edition oder +Version ändern will, wählt dort **„Etwas anderes waehlen"** oder gleich den +Assistenten. + +#### Die Einzelschritte > **In der Oberfläche geht das als Assistent:** **image → „Image beschaffen"** > führt in einem Durchgang durch Edition, Version und Bezugsweg, setzt danach @@ -1931,7 +1972,7 @@ Eine Dateiauswahl mit Verzeichnisnavigation ist eingebaut. | Kommando | Wirkung | |---|---| -| `up` / `down` / `restart` / `pull` | Stack steuern | +| `up [--no-fetch]` / `down` / `restart` / `pull` | Stack steuern; `up` holt ein fehlendes Image selbst | | `status` | Container, Sites, Zugangsadressen | | `logs [-f]` | Container-Logs | | `sites` | Sites im Container auflisten | @@ -1942,6 +1983,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 get` | Image über den eingestellten Bezugsweg holen | | `image status\|list\|versions\|repos\|why\|test\|pull\|download\|load\|use` | Checkmk-Image beschaffen, auswählen und Fehler erklären | | `browser [--engine …]` | Terminal-Browser im Container – Proxy Manager lokal bedienen | | `config list\|get\|set\|edit` | Einstellungen der `.env` anzeigen und ändern | diff --git a/README_en.md b/README_en.md index 2638c9b..7885b23 100644 --- a/README_en.md +++ b/README_en.md @@ -546,6 +546,7 @@ The most important settings: | `CMK_RUNTIME` | empty = auto-detect, otherwise `docker` or `podman` | | `CMK_IMAGE` | **the image actually used**, always fully qualified – see [chapter 8](#8-obtaining-the-checkmk-image-raw-enterprise--co) | | `CMK_EDITION`, `CMK_VERSION` | inputs for the image downloader only | +| `CMK_IMAGE_SOURCE` | `auto`/`registry`/`download` – where the image is fetched from | | `CMK_REGISTRY_USER/-PASSWORD` | login for `registry.checkmk.com` (Enterprise) | | `CMK_DOWNLOAD_USER/-PASSWORD` | login for the Checkmk download portal | | `CMK_SITE_ID` | the site the container creates and starts | @@ -842,7 +843,46 @@ 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 +### 8.6 Fetching the image – one command, three routes + +Once edition and version are set, this is enough: + +```bash +sudo ./scripts/cmk-manage.sh image get +``` + +Where it fetches from is controlled by **`CMK_IMAGE_SOURCE`**: + +| Value | Effect | +|---|---| +| `auto` (default) | registry first, then the download portal | +| `registry` | registry only | +| `download` | tarball from the download portal only | + +Deviate once with `image get --source download`. + +`auto` is the sensible default because registries only keep the most recent +patch levels – an older version needed for a migration then only exists in the +download portal. The switch happens automatically, without asking. + +**`up` fetches automatically.** If the image is missing locally and edition and +version are set, `up` obtains it first through this route – otherwise compose +attempts a plain pull, which must fail for a version that only exists in the +archive: + +``` +[ INFO ] Das Image ist lokal nicht vorhanden - hole es (auto) ... +[ INFO ] Bezugsweg 'auto': zuerst die Registry ... +[ WARN ] Aus der Registry nicht zu bekommen - versuche das Downloadportal. +``` + +`up --no-fetch` suppresses it. + +In the interface this is under **image → "Image holen"**. Only the source is +asked for there – the configured one is marked. To change edition or version, +pick **"Etwas anderes waehlen"** or the wizard directly. + +#### The individual steps > **In the interface this is a wizard:** **image → "Image beschaffen"** walks > through edition, version and source in one go, then sets `CMK_EDITION`, @@ -1930,7 +1970,7 @@ A file chooser with directory navigation is built in. | Command | Effect | |---|---| -| `up` / `down` / `restart` / `pull` | control the stack | +| `up [--no-fetch]` / `down` / `restart` / `pull` | control the stack; `up` fetches a missing image itself | | `status` | containers, sites, access addresses | | `logs [-f]` | container logs | | `sites` | list the sites in the container | @@ -1941,6 +1981,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 get` | fetch the image via the configured route | | `image status\|list\|versions\|repos\|why\|test\|pull\|download\|load\|use` | obtain and select the Checkmk image, and explain failures | | `browser [--engine …]` | terminal browser in a container – operate the Proxy Manager locally | | `config list\|get\|set\|edit` | show and change settings in `.env` | diff --git a/scripts/cmk-manage.sh b/scripts/cmk-manage.sh index 5636fcd..3a15e5b 100755 --- a/scripts/cmk-manage.sh +++ b/scripts/cmk-manage.sh @@ -43,7 +43,9 @@ KOMMANDOS - Oberflaeche gui | menu ncurses-Oberflaeche starten (dialog/whiptail) KOMMANDOS - Stack - up Stack starten (compose up -d) + up [--no-fetch] Stack starten (compose up -d). Fehlt das Image + lokal, wird es zuvor ueber CMK_IMAGE_SOURCE geholt; + --no-fetch unterdrueckt das down Stack stoppen und Container entfernen restart Stack neu starten pull Images aktualisieren @@ -128,6 +130,10 @@ KOMMANDOS - Checkmk-Image beschaffen --version V Version fuer die Pruefung des Downloadportals --user U --password P statt der Werte aus der .env --only registry|download nur einen Bezugsweg pruefen + image get [Opt.] Image ueber den eingestellten Bezugsweg holen + --source registry|download|auto (Vorgabe: CMK_IMAGE_SOURCE) + auto = erst Registry, dann Downloadportal + --edition E --version V sonst aus der .env image pull [Opt.] Image aus einer Registry holen --edition E raw|community|free|cloud|managed|pro|ultimate| ultimatemt|enterprise (Vorgabe: CMK_EDITION) @@ -656,6 +662,7 @@ EOF log "Hole Image: $ref" if ! $RUNTIME pull "$ref"; then err "Das Image '$ref' konnte nicht geholt werden." + if [ -n "${IMAGE_QUIET_FAIL:-}" ]; then return 1; fi if [ "$reg" != "docker.io" ] || [ -n "$user" ]; then image_diagnose_ref "$ref" || true return 1 @@ -1329,6 +1336,67 @@ EOF return 1 } +# --------------------------------------------------------------------- +# Image holen - ueber den eingestellten Bezugsweg +# +# CMK_IMAGE_SOURCE bestimmt, woher: +# registry nur aus der Registry +# download nur als Tarball vom Downloadportal +# auto erst Registry, dann Tarball (Vorgabe) +# +# "auto" ist die sinnvolle Vorgabe, weil Registries nur die juengsten +# Patchstaende vorhalten. Eine aeltere, fuer eine Migration noetige +# Version liegt dann nur noch im Downloadportal. +# --------------------------------------------------------------------- +image_source_default() { + case "$(printf '%s' "${CMK_IMAGE_SOURCE:-auto}" | tr 'A-Z' 'a-z')" in + registry|reg|r) printf 'registry\n' ;; + download|dl|tarball|d) printf 'download\n' ;; + *) printf 'auto\n' ;; + esac +} + +image_cmd_get() { + local edition="${CMK_EDITION:-}" version="${CMK_VERSION:-}" src="" + local -a extra=() + while [ $# -gt 0 ]; do + case "$1" in + --edition) edition="$2"; shift 2 ;; + --version) version="$2"; shift 2 ;; + --source) src="$2"; shift 2 ;; + --user) extra+=(--user "$2"); shift 2 ;; + --password) extra+=(--password "$2"); shift 2 ;; + *) die "Unbekannte Option fuer 'image get': $1" ;; + esac + done + [ -n "$src" ] || src="$(image_source_default)" + case "$src" in registry|download|auto) : ;; + *) die "--source: registry | download | auto" ;; esac + [ -n "$edition" ] || die "Keine Edition eingestellt (CMK_EDITION oder --edition)." + [ -n "$version" ] || die "Keine Version eingestellt (CMK_VERSION oder --version)." + + case "$src" in + registry) + image_cmd_pull --edition "$edition" --version "$version" --remember ${extra[@]+"${extra[@]}"} ;; + download) + image_cmd_download --edition "$edition" --version "$version" --remember ${extra[@]+"${extra[@]}"} ;; + auto) + log "Bezugsweg 'auto': zuerst die Registry ..." + if IMAGE_QUIET_FAIL=1 image_cmd_pull --edition "$edition" --version "$version" \ + --remember ${extra[@]+"${extra[@]}"}; then + return 0 + fi + warn "Aus der Registry nicht zu bekommen - versuche das Downloadportal." + if image_cmd_download --edition "$edition" --version "$version" \ + --remember ${extra[@]+"${extra[@]}"}; then + return 0 + fi + err "Weder Registry noch Downloadportal haben geliefert." + image_diagnose_ref "$(edition_repo "$edition"):$version" || true + return 1 ;; + esac +} + # --------------------------------------------------------------------- # image versions - verfuegbare Versionen auflisten # @@ -1632,8 +1700,9 @@ cmd_image() { versions|tags) image_cmd_versions "$@" ;; repos|repo) image_cmd_repos "$@" ;; why|diagnose) image_diagnose_ref "${1:-${CMK_IMAGE:-}}" ;; + get|fetch) image_cmd_get "$@" ;; *) die "Unbekanntes Unterkommando 'image $sub'. - Moeglich: status | list | versions | repos | why | test | pull | download | load | use" ;; + Moeglich: status | list | versions | repos | why | test | get | pull | download | load | use" ;; esac } @@ -1659,6 +1728,20 @@ cmd_up() { else log "Starte Stack (${RUNTIME}) - ohne NGINX Proxy Manager (NPM_ENABLED=off) ..." fi + # Fehlt das Image lokal, es selbst holen - ueber den eingestellten + # Bezugsweg. Sonst versucht compose einen nackten Pull, der bei einer + # nur im Downloadportal vorhandenen Version scheitern muss. + if [ -z "${UP_NO_FETCH:-}" ] && [ -n "${CMK_IMAGE:-}" ] \ + && ! image_exists_local "$CMK_IMAGE" \ + && [ -n "${CMK_EDITION:-}" ] && [ -n "${CMK_VERSION:-}" ]; then + log "Das Image ist lokal nicht vorhanden - hole es ($(image_source_default)) ..." + if ! image_cmd_get; then + err "Das Image konnte nicht beschafft werden - der Stack wird nicht gestartet." + return 1 + fi + load_env "${ENV_FILE:-$PROJECT_DIR/.env}" + fi + if ! compose up -d "${svc[@]}"; then echo err "Der Stack konnte nicht gestartet werden." @@ -2790,6 +2873,7 @@ runtime|TZ|text|Zeitzone|| image|CMK_IMAGE|info|VERWENDETES Image (setzt der Assistent)||1 image|CMK_EDITION|info|Edition (setzt der Assistent)||1 image|CMK_VERSION|info|Version (setzt der Assistent)||1 +image|CMK_IMAGE_SOURCE|choice|Bezugsweg beim Holen|auto:registry:download| image|CMK_REGISTRY|text|Registry fuer Enterprise||1 image|CMK_REGISTRY_USER|text|Registry-Benutzer||1 image|CMK_REGISTRY_PASSWORD|password|Registry-Kennwort||1 @@ -4077,7 +4161,8 @@ gui_image_menu() { Edition/Version: ${CMK_EDITION:-raw} / ${CMK_VERSION:-?}" \ status "Status und lokale Images anzeigen" \ versions "Verfuegbare Versionen auflisten" \ - holen "Image beschaffen (Assistent: Edition, Version, Bezugsweg)" \ + holen "Image holen (Registry oder Downloadportal)" \ + wizard "Assistent: Edition, Version und Bezugsweg waehlen" \ test "Zugangsdaten pruefen (Registry und Downloadportal)" \ use "Vorhandenes lokales Image auswaehlen" \ back "zurueck")" || return 0 @@ -4085,7 +4170,8 @@ Edition/Version: ${CMK_EDITION:-raw} / ${CMK_VERSION:-?}" \ 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 ;; - holen) gui_image_wizard || true ;; + holen) gui_image_get || true ;; + wizard) gui_image_wizard || true ;; test) gui_image_test || true ;; use) gui_image_use || true ;; back) return 0 ;; @@ -4296,6 +4382,69 @@ Wirksam wird das mit 'Stack steuern -> Stack starten' (die Container werden dabei neu erstellt)." } +# Holen, wenn Edition und Version schon feststehen: nur noch die Frage +# nach dem Bezugsweg. Der volle Assistent bleibt als Wahlmoeglichkeit. +gui_image_get() { + if [ -z "${CMK_EDITION:-}" ] || [ -z "${CMK_VERSION:-}" ]; then + ui_msg "Erst Edition und Version" \ +"Es ist noch keine Edition bzw. Version eingestellt. + +Der Assistent fragt beides ab und laesst sich gleich +anschliessen." + gui_image_wizard || true + return 0 + fi + + local ref="" vorgabe + if edition_known "${CMK_EDITION}" 2>/dev/null; then + ref="$(edition_repo "$CMK_EDITION"):$CMK_VERSION" + fi + vorgabe="$(image_source_default)" + + # Der eingestellte Weg wird gekennzeichnet, statt ihn doppelt + # aufzufuehren - sonst gaebe es zwei Eintraege mit derselben Kennung. + local m_auto="erst Registry, dann Downloadportal" + local m_reg="nur aus der Registry" + local m_dl="nur als Tarball vom Downloadportal" + case "$vorgabe" in + auto) m_auto="$m_auto (eingestellt)" ;; + registry) m_reg="$m_reg (eingestellt)" ;; + download) m_dl="$m_dl (eingestellt)" ;; + esac + + local sel + sel="$(ui_menu "Image holen" \ +"Edition/Version: ${CMK_EDITION} / ${CMK_VERSION}${ref:+ +Registry-Referenz: $ref} + +Woher soll das Image geholt werden?" \ + auto "$m_auto" \ + registry "$m_reg" \ + download "$m_dl" \ + datei "Vorhandene Tarball-Datei einspielen" \ + assistent "Etwas anderes waehlen (Edition/Version aendern)")" || return 0 + + case "$sel" in + assistent) gui_image_wizard || true; return 0 ;; + datei) + local lf + lf="$(ui_pick_file "${IMAGE_DIR:-$PROJECT_DIR/images}" '*.tar.gz')" || return 0 + [ -n "$lf" ] || return 0 + ui_run "Image einspielen" bash -c \ + "cd '$PROJECT_DIR' && NO_COLOR=1 '$SELF' -y image load --file '$lf'" + load_env "${ENV_FILE:-$PROJECT_DIR/.env}" + return 0 ;; + esac + + ui_run "Image holen ($sel)" bash -c \ + "cd '$PROJECT_DIR' && NO_COLOR=1 '$SELF' -y image get --source '$sel'" + load_env "${ENV_FILE:-$PROJECT_DIR/.env}" + + local f; f="$(mktemp)" + NO_COLOR=1 cmd_image status >"$f" 2>&1 || true + ui_text "Stand nach dem Holen" "$f"; rm -f "$f" +} + gui_image_versions() { local ed ed="$(gui_image_pick_edition)" || return 0 @@ -4517,7 +4666,8 @@ gui_settings_category() { done < <(settings_defs) # Zusatzaktionen, die inhaltlich zur Kategorie gehoeren case "$cat" in - image) items+=("__wizard__" ">> Image beschaffen (Edition, Version, Bezugsweg)") + image) items+=("__get__" ">> Image jetzt holen (Registry oder Downloadportal)") + items+=("__wizard__" ">> Assistent: Edition, Version, Bezugsweg") items+=("__test__" ">> Zugangsdaten jetzt pruefen (Registry + Downloadportal)") ;; npm) items+=("__proxy__" ">> Proxy-Hosts anlegen/verwalten") items+=("__npm__" ">> Proxy Manager: Stand und Admin-Port anzeigen") ;; @@ -4528,6 +4678,7 @@ gui_settings_category() { sel="$(ui_menu "$title" "Eintrag waehlen und mit ENTER aendern:" "${items[@]}")" || return 0 case "$sel" in back) return 0 ;; + __get__) gui_image_get || true; continue ;; __wizard__) gui_image_wizard || true; continue ;; __proxy__) gui_proxy_menu || true; continue ;; __test__) gui_image_test || true; continue ;; @@ -5051,7 +5202,8 @@ main() { local cmd="${1:-gui}"; [ $# -gt 0 ] && shift || true case "$cmd" in gui|menu) gui_main ;; - up|start) cmd_up ;; + up|start) if [ "${1:-}" = "--no-fetch" ]; then UP_NO_FETCH=1; fi + cmd_up ;; down|stop) cmd_down ;; restart) cmd_restart || true ;; pull) cmd_pull || true ;; diff --git a/scripts/lib/common.sh b/scripts/lib/common.sh index 65c85d0..72bf020 100644 --- a/scripts/lib/common.sh +++ b/scripts/lib/common.sh @@ -45,6 +45,7 @@ load_env() { CMK_IMAGE="${CMK_IMAGE:-docker.io/checkmk/check-mk-raw:2.3.0-latest}" NPM_ENABLED="${NPM_ENABLED:-on}" BACKUP_AUTO="${BACKUP_AUTO:-off}" + CMK_IMAGE_SOURCE="${CMK_IMAGE_SOURCE:-auto}" PROXY_FORWARD_HOST="${PROXY_FORWARD_HOST:-127.0.0.1}" PROXY_FORWARD_PORT="${PROXY_FORWARD_PORT:-5000}" NPM_ADMIN_PORT="${NPM_ADMIN_PORT:-81}"