From b8d18e819c5abe60354bae269d4c76969ab4765f Mon Sep 17 00:00:00 2001 From: Torben Nehmer Date: Sun, 12 Jul 2026 15:55:20 +0200 Subject: [PATCH] Add logging functions and improve error handling in test registry script --- README.md | 7 +++ scripts/test-registry-image.sh | 106 +++++++++++++++++++++++++++------ 2 files changed, 96 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index fe66d66..cf80b91 100644 --- a/README.md +++ b/README.md @@ -176,6 +176,13 @@ Default-Verhalten: Der Registry-Login fragt das Passwort oder einen PAT interaktiv und unsichtbar ab. +Auth-Handling ist absichtlich ephemeral: + +- Das Script schreibt keine Credentials in `~/.docker/config.json`. +- Fuer `docker` wird ein temporäres `DOCKER_CONFIG`-Verzeichnis verwendet. +- Fuer `podman` wird eine temporäre `REGISTRY_AUTH_FILE` verwendet. +- Beides wird beim Script-Ende automatisch geloescht. + Beispiel: ```bash diff --git a/scripts/test-registry-image.sh b/scripts/test-registry-image.sh index 6bdd68d..7d3281e 100755 --- a/scripts/test-registry-image.sh +++ b/scripts/test-registry-image.sh @@ -10,6 +10,26 @@ USERNAME="torben" RUNTIME="" REQUIRED_LABELS=() +log_ts() { + date '+%Y-%m-%d %H:%M:%S' +} + +log_info() { + printf '[%s] [INFO] %s\n' "$(log_ts)" "$*" +} + +log_ok() { + printf '[%s] [ OK ] %s\n' "$(log_ts)" "$*" +} + +log_warn() { + printf '[%s] [WARN] %s\n' "$(log_ts)" "$*" >&2 +} + +log_fail() { + printf '[%s] [FAIL] %s\n' "$(log_ts)" "$*" >&2 +} + usage() { cat <<'EOF' Usage: scripts/test-registry-image.sh [options] @@ -63,37 +83,41 @@ while [[ $# -gt 0 ]]; do done if [[ -z "$TAG" ]]; then - echo "Tag must not be empty" >&2 + log_fail "Tag must not be empty" exit 1 fi if [[ -z "$RUNTIME" ]]; then if command -v docker >/dev/null 2>&1; then RUNTIME="docker" + log_info "Runtime auto-detected: docker" elif command -v podman >/dev/null 2>&1; then RUNTIME="podman" + log_info "Runtime auto-detected: podman" else - echo "Neither docker nor podman is available" >&2 + log_fail "Neither docker nor podman is available" exit 1 fi fi if ! command -v "$RUNTIME" >/dev/null 2>&1; then - echo "Container runtime not found: $RUNTIME" >&2 + log_fail "Container runtime not found: $RUNTIME" exit 1 fi if ! command -v curl >/dev/null 2>&1; then - echo "curl is required" >&2 + log_fail "curl is required" exit 1 fi +log_info "Using runtime: $RUNTIME" + script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" repo_root="$(cd "$script_dir/.." && pwd)" hash_dir="$repo_root/demo/token-hashes" if [[ ! -d "$hash_dir" ]]; then - echo "Demo hash directory not found: $hash_dir" >&2 + log_fail "Demo hash directory not found: $hash_dir" exit 1 fi @@ -101,16 +125,41 @@ image_ref="$REGISTRY_HOST/$OWNER/$IMAGE_NAME:$TAG" container_name="authproxy-registry-test-$$" container_id="" host_port="" +tmp_dir="" +auth_mode="" cleanup() { local exit_code=$? if [[ -n "$container_id" ]]; then + log_info "Cleaning up container: $container_id" "$RUNTIME" rm -f "$container_id" >/dev/null 2>&1 || true fi + if [[ -n "$tmp_dir" && -d "$tmp_dir" ]]; then + log_info "Removing temporary auth directory" + rm -rf "$tmp_dir" + fi exit "$exit_code" } trap cleanup EXIT +tmp_dir="$(mktemp -d)" +log_info "Created temporary workspace: $tmp_dir" + +if [[ "$RUNTIME" == "docker" ]]; then + auth_mode="docker_config" + mkdir -p "$tmp_dir/docker-config" + log_info "Auth mode: docker with temporary DOCKER_CONFIG" +elif [[ "$RUNTIME" == "podman" ]]; then + auth_mode="podman_auth_file" + log_info "Auth mode: podman with temporary REGISTRY_AUTH_FILE" +else + log_fail "Unsupported runtime: $RUNTIME" + exit 1 +fi + +log_info "Test image: $image_ref" +log_info "Demo hash source: $hash_dir" + printf 'Registry password for %s@%s: ' "$USERNAME" "$REGISTRY_HOST" >&2 stty -echo IFS= read -r registry_password @@ -118,17 +167,33 @@ stty echo printf '\n' >&2 if [[ -z "$registry_password" ]]; then - echo "Empty password/token is not allowed" >&2 + log_fail "Empty password/token is not allowed" exit 1 fi -printf '%s' "$registry_password" | "$RUNTIME" login "$REGISTRY_HOST" --username "$USERNAME" --password-stdin >/dev/null +log_info "Logging in to registry (credentials are not printed)" +if [[ "$auth_mode" == "docker_config" ]]; then + printf '%s' "$registry_password" | \ + env DOCKER_CONFIG="$tmp_dir/docker-config" \ + "$RUNTIME" login "$REGISTRY_HOST" --username "$USERNAME" --password-stdin >/dev/null +elif [[ "$auth_mode" == "podman_auth_file" ]]; then + printf '%s' "$registry_password" | \ + env REGISTRY_AUTH_FILE="$tmp_dir/podman-auth.json" \ + "$RUNTIME" login "$REGISTRY_HOST" --username "$USERNAME" --password-stdin >/dev/null +fi unset registry_password +log_ok "Registry login successful" -echo "Pulling $image_ref" -"$RUNTIME" pull "$image_ref" >/dev/null +log_info "Pulling image: $image_ref" +if [[ "$auth_mode" == "docker_config" ]]; then + env DOCKER_CONFIG="$tmp_dir/docker-config" "$RUNTIME" pull "$image_ref" >/dev/null +else + env REGISTRY_AUTH_FILE="$tmp_dir/podman-auth.json" "$RUNTIME" pull "$image_ref" >/dev/null +fi +log_ok "Image pull complete" for required_label in "${REQUIRED_LABELS[@]}"; do + log_info "Validating required label: $required_label" label_key="$required_label" label_expected="" if [[ "$required_label" == *=* ]]; then @@ -138,16 +203,17 @@ for required_label in "${REQUIRED_LABELS[@]}"; do label_value="$("$RUNTIME" image inspect "$image_ref" --format "{{ index .Config.Labels \"$label_key\" }}" 2>/dev/null || true)" if [[ -z "$label_value" || "$label_value" == "" ]]; then - echo "Required image label missing: $label_key" >&2 + log_fail "Required image label missing: $label_key" exit 1 fi if [[ -n "$label_expected" && "$label_value" != "$label_expected" ]]; then - echo "Image label mismatch for $label_key: expected $label_expected, got $label_value" >&2 + log_fail "Image label mismatch for $label_key: expected $label_expected, got $label_value" exit 1 fi + log_ok "Label check passed: $label_key=$label_value" done -echo "Starting container from $image_ref" +log_info "Starting container from image" container_id="$($RUNTIME run -d \ --name "$container_name" \ -p 127.0.0.1::8080 \ @@ -156,23 +222,28 @@ container_id="$($RUNTIME run -d \ -e AUTH_PROXY_LOG_LEVEL=debug \ -v "$hash_dir:/token-hashes:ro" \ "$image_ref")" +log_ok "Container started: $container_id" host_port="$($RUNTIME port "$container_id" 8080/tcp | awk -F: 'NR==1 {print $NF}')" if [[ -z "$host_port" ]]; then - echo "Failed to determine mapped host port" >&2 + log_fail "Failed to determine mapped host port" "$RUNTIME" logs "$container_id" >&2 || true exit 1 fi base_url="http://127.0.0.1:$host_port" +log_info "Container is reachable at: $base_url" wait_for_health() { local attempt http_code + log_info "Waiting for health endpoint to return 200" for attempt in $(seq 1 30); do http_code="$(curl -s -o /dev/null -w '%{http_code}' "$base_url/healthz" || true)" if [[ "$http_code" == "200" ]]; then + log_ok "Health endpoint is ready after $attempt attempt(s)" return 0 fi + log_info "Health attempt $attempt/30 returned: $http_code" sleep 1 done return 1 @@ -185,22 +256,23 @@ assert_status() { local http_code http_code="$(curl -s -o /dev/null -w '%{http_code}' "$@")" if [[ "$http_code" != "$expected" ]]; then - echo "FAIL: $description expected $expected, got $http_code" >&2 + log_fail "$description expected $expected, got $http_code" "$RUNTIME" logs "$container_id" >&2 || true exit 1 fi - echo "OK: $description -> $http_code" + log_ok "$description -> $http_code" } if ! wait_for_health; then - echo "Container did not become healthy: $image_ref" >&2 + log_fail "Container did not become healthy: $image_ref" "$RUNTIME" logs "$container_id" >&2 || true exit 1 fi +log_info "Running HTTP assertions" assert_status 200 "healthz" "$base_url/healthz" assert_status 401 "missing token" "$base_url/" assert_status 401 "wrong token" -H "Authorization: Bearer wrong" "$base_url/" assert_status 200 "demo-token-1" -H "Authorization: Bearer demo-token-1" "$base_url/" -echo "Registry image test succeeded: $image_ref" \ No newline at end of file +log_ok "Registry image test succeeded: $image_ref" \ No newline at end of file