image repos: herausfinden, was die Registry wirklich anbietet
"Login Succeeded" und trotzdem "unable to copy from source": der
Repository-Pfad enterprise/check-mk-enterprise war geraten, nicht
belegt. Statt weiter zu raten fragt das Werkzeug jetzt nach.
image repos [--edition E] [--registry R] [--user/--password]
fragt zuerst /v2/_catalog ab (sperren viele Registries) und probiert
danach die ueblichen Pfade durch, je Edition und deren Aliasnamen:
<ed>/check-mk-<ed>, check-mk-<ed>, checkmk/check-mk-<ed>,
enterprise/check-mk-<ed>
Gemeldet wird pro Pfad der HTTP-Status samt Tag-Anzahl. Scheitert ein
"image pull" gegen eine private Registry, laeuft die Pruefung von
selbst an und zeigt gleich, was dort liegt.
Wichtig bei der Deutung und deshalb auch so beschriftet: 401 heisst
nicht "vorhanden". Docker Hub antwortet auch auf nicht existierende
Repositories mit 401. Verlaesslich sind nur 200 und 404.
Nebenbei am Versionsarchiv geklaert, dass die Editionsumbenennung erst
mit 2.5 greift:
2.4.0p9 -> check-mk-{raw,enterprise,cloud,managed}-docker-...
2.5.0p13 -> check-mk-{community,pro,ultimate,ultimatemt}-docker-...
Fuer 2.4 ist "--edition enterprise" also richtig.
registry_get_token nimmt jetzt einen frei waehlbaren Scope, damit auch
registry:catalog:* angefordert werden kann.
Gegen Docker Hub verifiziert: findet checkmk/check-mk-raw (2394 Tags)
und checkmk/check-mk-community (534 Tags); gegen registry.checkmk.com
ohne Zugangsdaten sauberer Fehlbericht statt Haenger.
Dokumentiert als Abschnitt 8.8 in beiden Sprachfassungen.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+132
-4
@@ -116,6 +116,8 @@ KOMMANDOS - Checkmk-Image beschaffen
|
||||
--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 repos [Opt.] herausfinden, welche Repositories die Registry
|
||||
wirklich anbietet (Katalog + uebliche Pfade)
|
||||
image test [Opt.] Zugangsdaten pruefen, ohne etwas herunterzuladen
|
||||
--edition E Edition, deren Repository geprueft wird
|
||||
--version V Version fuer die Pruefung des Downloadportals
|
||||
@@ -607,6 +609,13 @@ EOF
|
||||
log "Hole Image: $ref"
|
||||
if ! $RUNTIME pull "$ref"; then
|
||||
err "Das Image '$ref' konnte nicht geholt werden."
|
||||
if [ "$reg" != "docker.io" ] && [ -n "$user" ]; then
|
||||
warn "Die Anmeldung hat geklappt, der Pfad oder das Tag aber nicht.
|
||||
Ich sehe nach, was diese Registry tatsaechlich anbietet ..."
|
||||
image_cmd_repos --edition "$edition" --registry "$reg" \
|
||||
--user "$user" --password "$pass" || true
|
||||
return 1
|
||||
fi
|
||||
if [ "$edition" = enterprise ]; then
|
||||
cat >&2 <<'EOF'
|
||||
|
||||
@@ -1134,8 +1143,9 @@ image_cmd_test() {
|
||||
# ---------------------------------------------------------------------
|
||||
|
||||
# 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"
|
||||
registry_get_token() { # api repo user pass [scope] -> Token auf stdout
|
||||
local api="$1" repo="$2" user="$3" pass="$4" scope="${5:-}"
|
||||
[ -n "$scope" ] || scope="repository:$repo:pull"
|
||||
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
|
||||
@@ -1149,7 +1159,7 @@ registry_get_token() { # api repo user pass -> Token auf stdout
|
||||
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 url="$realm?service=$service&scope=$scope"
|
||||
local body netrc=""
|
||||
if [ -n "$user" ]; then
|
||||
netrc="$(netrc_make "$user" "$pass" "$api" "$realm_host")"
|
||||
@@ -1198,6 +1208,123 @@ download_versions() { # user pass -> Versionsverzeichnisse
|
||||
| sed -E 's|href="([^"/]+)/?"|\1|' | sort -u
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
# Welches Repository heisst in der Registry wie?
|
||||
#
|
||||
# Der Pfad ist nicht zu erraten - "Login Succeeded" heisst noch lange
|
||||
# nicht, dass enterprise/check-mk-enterprise existiert. Deshalb erst den
|
||||
# Katalog fragen und, falls der gesperrt ist, die ueblichen Pfade
|
||||
# durchprobieren. HTTP 404 = gibt es nicht, 401/403 = keine Berechtigung,
|
||||
# 200 = nutzbar.
|
||||
# ---------------------------------------------------------------------
|
||||
registry_catalog() { # api user pass -> Repository-Namen
|
||||
local api="$1" user="$2" pass="$3"
|
||||
local token; token="$(registry_get_token "$api" "" "$user" "$pass" "registry:catalog:*")"
|
||||
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
|
||||
curl "${a[@]}" "https://$api/v2/_catalog?n=1000" 2>/dev/null \
|
||||
| tr ',' '\n' | grep -oE '"[a-z0-9][a-z0-9._/-]*"' | tr -d '"' \
|
||||
| grep -v '^repositories$' | sed '/^$/d' | sort -u
|
||||
}
|
||||
|
||||
registry_repo_candidates() { # edition -> moegliche Repository-Pfade
|
||||
local edition="$1" a
|
||||
for a in $(edition_aliases "$edition"); do
|
||||
printf '%s/check-mk-%s\n' "$a" "$a"
|
||||
printf 'check-mk-%s\n' "$a"
|
||||
printf 'checkmk/check-mk-%s\n' "$a"
|
||||
printf 'enterprise/check-mk-%s\n' "$a"
|
||||
done
|
||||
}
|
||||
|
||||
# Status eines Repositories ermitteln: 200 / 401 / 403 / 404 / 000
|
||||
registry_repo_status() { # api repo user pass -> "code anzahl_tags"
|
||||
local api="$1" repo="$2" user="$3" pass="$4"
|
||||
local token; token="$(registry_get_token "$api" "$repo" "$user" "$pass")"
|
||||
local -a a=(-sS -o /tmp/.cmkrepo.$$ -w '%{http_code}' --max-time 30)
|
||||
[ -n "$token" ] && a+=(-H "Authorization: Bearer $token")
|
||||
local code
|
||||
code="$(curl "${a[@]}" "https://$api/v2/$repo/tags/list" 2>/dev/null)" || code=000
|
||||
local n=0
|
||||
[ "${code:-000}" = 200 ] && n="$(tr ',' '\n' <"/tmp/.cmkrepo.$$" 2>/dev/null | grep -c '"' || echo 0)"
|
||||
rm -f "/tmp/.cmkrepo.$$"
|
||||
printf '%s %s\n' "${code:-000}" "$n"
|
||||
}
|
||||
|
||||
image_cmd_repos() {
|
||||
local edition="${CMK_EDITION:-enterprise}" reg="${CMK_REGISTRY:-registry.checkmk.com}"
|
||||
local user="${CMK_REGISTRY_USER:-}" pass="${CMK_REGISTRY_PASSWORD:-}"
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--edition) edition="$2"; shift 2 ;;
|
||||
--registry) reg="$2"; shift 2 ;;
|
||||
--user) user="$2"; shift 2 ;;
|
||||
--password) pass="$2"; shift 2 ;;
|
||||
*) die "Unbekannte Option fuer 'image repos': $1" ;;
|
||||
esac
|
||||
done
|
||||
command -v curl >/dev/null 2>&1 || die "Fuer 'image repos' wird curl benoetigt."
|
||||
local api; api="$(registry_api_host "$reg")"
|
||||
|
||||
printf '\n%sRegistry %s%s\n' "$C_BLD" "$reg" "$C_RST"
|
||||
[ -n "$user" ] || warn "Keine Zugangsdaten hinterlegt - ohne Anmeldung ist hier wenig zu sehen."
|
||||
|
||||
printf '\n%sKatalog (/v2/_catalog)%s\n' "$C_BLD" "$C_RST"
|
||||
local -a cat=()
|
||||
mapfile -t cat < <(registry_catalog "$api" "$user" "$pass" | grep -iE 'check|mk' | head -50)
|
||||
if [ ${#cat[@]} -gt 0 ]; then
|
||||
printf ' %s\n' "${cat[@]}"
|
||||
else
|
||||
printf ' (nicht abrufbar - viele Registries sperren den Katalog)\n'
|
||||
fi
|
||||
|
||||
printf '\n%sUebliche Pfade fuer "%s" durchprobiert%s\n' "$C_BLD" "$edition" "$C_RST"
|
||||
printf ' %-6s %-8s %s\n' "STATUS" "TAGS" "PFAD"
|
||||
printf ' %s200 = nutzbar, 404 = gibt es nicht, 401/403 = kein Zugriff%s\n' "$C_BLU" "$C_RST"
|
||||
local cand code n line ok=""
|
||||
while IFS= read -r cand; do
|
||||
[ -n "$cand" ] || continue
|
||||
line="$(registry_repo_status "$api" "$cand" "$user" "$pass")"
|
||||
code="${line%% *}"; n="${line##* }"
|
||||
case "$code" in
|
||||
200) printf ' %s%-6s%s %-8s %s\n' "$C_GRN" "$code" "$C_RST" "$n" "$cand"
|
||||
[ -z "$ok" ] && ok="$cand" ;;
|
||||
401|403) printf ' %s%-6s%s %-8s %s (kein Zugriff - oder gibt es nicht;\n%38sviele Registries verbergen das)\n' \
|
||||
"$C_YEL" "$code" "$C_RST" "-" "$cand" "" ;;
|
||||
404) printf ' %-6s %-8s %s (gibt es nicht)\n' "$code" "-" "$cand" ;;
|
||||
*) printf ' %-6s %-8s %s\n' "${code:-000}" "-" "$cand" ;;
|
||||
esac
|
||||
done < <(registry_repo_candidates "$edition" | awk '!seen[$0]++')
|
||||
|
||||
echo
|
||||
if [ -n "$ok" ]; then
|
||||
ok "Nutzbar: $reg/$ok"
|
||||
cat <<EOF
|
||||
|
||||
${C_BLD}Weiter${C_RST}
|
||||
Tags ansehen : $SELF image versions --source registry --edition $edition
|
||||
Image setzen : $SELF image use $reg/$ok:<version>
|
||||
EOF
|
||||
else
|
||||
err "Unter '$reg' wurde kein nutzbares Repository fuer '$edition' gefunden."
|
||||
cat <<EOF
|
||||
|
||||
Moegliche Gruende:
|
||||
* Die Subskription schliesst den Registry-Zugang nicht ein.
|
||||
Dann fuehrt der Tarball-Weg zum Ziel:
|
||||
$SELF image download --edition $edition --version <version>
|
||||
* Der Pfad heisst anders. Steht er im Kundenportal, laesst er sich
|
||||
direkt setzen:
|
||||
$SELF config set CMK_REGISTRY <registry>
|
||||
$SELF image use <registry>/<pfad>:<version>
|
||||
EOF
|
||||
fi
|
||||
echo
|
||||
}
|
||||
|
||||
image_cmd_versions() {
|
||||
local edition="${CMK_EDITION:-raw}" source="all" filter="" limit=25
|
||||
local ruser="${CMK_REGISTRY_USER:-}" rpass="${CMK_REGISTRY_PASSWORD:-}"
|
||||
@@ -1324,8 +1451,9 @@ cmd_image() {
|
||||
use|set) image_cmd_use "$@" ;;
|
||||
test|check) image_cmd_test "$@" ;;
|
||||
versions|tags) image_cmd_versions "$@" ;;
|
||||
repos|repo) image_cmd_repos "$@" ;;
|
||||
*) die "Unbekanntes Unterkommando 'image $sub'.
|
||||
Moeglich: status | list | versions | test | pull | download | load | use" ;;
|
||||
Moeglich: status | list | versions | repos | test | pull | download | load | use" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user