cockpit-kata/qcrows-inspect

122 lines
5.3 KiB
Bash
Executable File

#!/usr/bin/env bash
# ============================================================================
# qcrows-inspect — Read QCrows image metadata without full extraction
# ============================================================================
set -euo pipefail
CYAN='\033[0;36m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
FILE="${1:-}"
[[ -z "$FILE" ]] && { echo "Usage: qcrows-inspect <file.qcrows>"; exit 1; }
[[ ! -f "$FILE" ]] && { echo "File not found: $FILE" >&2; exit 1; }
# ─── Archive extraction helpers (single dispatch point) ──────────────────────
# Extract a file from the archive to stdout
tar_extract() {
local archive="$1"; shift
if [[ "$archive" == *.gz ]]; then
tar xzf "$archive" "$@" 2>/dev/null
else
tar xf "$archive" "$@" 2>/dev/null
fi
}
# List archive contents to stdout
tar_list() {
local archive="$1"
if [[ "$archive" == *.gz ]]; then
tar tzf "$archive" 2>/dev/null
else
tar tf "$archive" 2>/dev/null
fi
}
# ─── Read values from TOML content ──────────────────────────────────────────
get_val() {
echo "$META" | grep -E "^${1}" | head -1 | sed 's/.*= *//' | tr -d '"' | tr -d ' '
}
get_array() {
echo "$META" | grep -E "^${1}" | head -1 | sed 's/.*= *//' | tr -d '[]"' | sed 's/, */, /g'
}
get_section_val() {
local section="$1" key="$2"
echo "$META" | awk "/\[.*${section}.*\]/{found=1} found && /^${key}/{print; exit}"
}
# ─── Read metadata.toml ────────────────────────────────────────────────────
META="$(tar_extract "$FILE" -O ./metadata.toml 2>/dev/null || tar_extract "$FILE" -O metadata.toml 2>/dev/null || echo "")"
if [[ -z "$META" ]]; then
echo "Error: Could not read metadata.toml from archive" >&2
exit 1
fi
# ─── Format output ─────────────────────────────────────────────────────────
FMT=" %-16s ${CYAN}%s${NC}\n"
echo ""
echo -e "${GREEN}QCrows Image Inspection${NC}"
echo -e "${YELLOW}──────────────────────────────────────────────────────${NC}"
printf "$FMT" "Name:" "$(get_val 'name')"
printf "$FMT" "Version:" "$(get_val 'version')"
printf "$FMT" "Description:" "$(echo "$META" | grep '^description' | head -1 | sed "s/.*= *//;s/^\"//;s/\"$//")"
printf "$FMT" "Arch:" "$(get_val 'arch')"
printf "$FMT" "Created:" "$(get_val 'created_at')"
echo ""
echo -e "${YELLOW}Compatibility:${NC}"
printf "$FMT" "Hypervisors:" "$(get_array 'hypervisors')"
printf "$FMT" "Kata min:" "$(get_val 'kata_runtime_min')"
echo ""
# ─── Component details ─────────────────────────────────────────────────────
echo -e "${YELLOW}Components:${NC}"
k_included=$(get_section_val kernel included | sed 's/.*= *//' | tr -d ' ' || echo "false")
k_version=$(get_section_val kernel version | sed 's/.*= *//' | tr -d '"' || echo "unknown")
k_format=$(get_section_val kernel format | sed 's/.*= *//' | tr -d '"' || echo "vmlinuz")
k_size=$(get_section_val kernel size_mb | sed 's/.*= *//' | tr -d ' ' || echo "0")
printf "$FMT" "Kernel:" "${k_version} (${k_format})"
printf "$FMT" "Kernel size:" "${k_size} MiB"
printf "$FMT" "Kernel config:" "$(get_section_val kernel config_path | sed 's/.*= *//' | tr -d '"' || echo "missing")"
printf "$FMT" "Initrd:" "$(get_val 'type') (included=$(get_val 'included'))"
printf "$FMT" "Rootfs:" "$(get_val 'type')"
printf "$FMT" "Rootfs size:" "$(get_val 'size_mb') MiB"
boot_included=$(get_section_val boot_params included | sed 's/.*= *//' | tr -d ' ' || echo "false")
printf "$FMT" "Boot params:" "${boot_included}"
echo ""
# ─── Build info ─────────────────────────────────────────────────────────────
BUILD_SYS=$(get_section_val build system | sed 's/.*= *//' | tr -d '"' || true)
if [[ -n "$BUILD_SYS" ]]; then
echo -e "${YELLOW}Build:${NC}"
printf "$FMT" "System:" "$BUILD_SYS"
printf "$FMT" "Timestamp:" "$(get_section_val build timestamp | sed 's/.*= *//' | tr -d '"' || echo 'N/A')"
echo ""
fi
# ─── Menu entry ─────────────────────────────────────────────────────────────
MENU="$(tar_extract "$FILE" -O ./menu.toml 2>/dev/null || tar_extract "$FILE" -O menu.toml 2>/dev/null || echo "")"
if [[ -n "$MENU" ]]; then
menu_label=$(echo "$MENU" | grep '^label' | head -1 | sed 's/.*= *//' | tr -d '"' || echo "N/A")
menu_cat=$(echo "$MENU" | grep '^category' | head -1 | sed 's/.*= *//' | tr -d '"' || echo "N/A")
echo -e "${YELLOW}Menu Entry:${NC}"
printf "$FMT" "Label:" "$menu_label"
printf "$FMT" "Category:" "$menu_cat"
echo ""
fi
# ─── Archive contents (direct pipeline — no subshell loop) ──────────────────
echo -e "${YELLOW}Archive Contents:${NC}"
tar_list "$FILE" | sort | sed "s/^/ ${CYAN}/;s/$/${NC}/"
echo ""