Files
image-builder/scripts/image-builder.sh
2025-09-24 23:48:50 +02:00

330 lines
10 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
IFS=$'\n\t'
ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
CONFIG_DIR="$ROOT_DIR/config"
GLOBAL_CONFIG="$CONFIG_DIR/global/config.json"
ensure_dirs() {
mkdir -p "$CONFIG_DIR/global" "$CONFIG_DIR/projects" "$CONFIG_DIR/registries" "$ROOT_DIR/projects"
if [[ ! -f "$GLOBAL_CONFIG" ]]; then
cat >"$GLOBAL_CONFIG" <<EOF
{
"editor": "nano"
}
EOF
fi
}
ensure_prereqs() {
local bins=("docker" "git" "jq" "whiptail")
for b in "${bins[@]}"; do
if ! command -v "$b" >/dev/null 2>&1; then
echo "[WARN] Benötigtes Programm fehlt: $b"
fi
done
}
# -------------------------
# Konfigurations-Menü
# -------------------------
config_menu() {
while true; do
local builder_icon
builder_icon=$(get_builder_status_icon)
choice=$(whiptail --title "Konfiguration" --menu "Bitte wählen:" 20 70 10 \
1 "Abhängigkeiten installieren (docker, git, jq, whiptail)" \
2 "Buildx-Builder einrichten | Status: $builder_icon" \
3 "Globalen Editor setzen" \
0 "Zurück" \
3>&1 1>&2 2>&3) || return
case $choice in
1) install_dependencies;;
2) install_docker_and_buildx;;
3) set_editor;;
0) return;;
esac
done
}
get_builder_status_icon() {
if docker buildx ls 2>/dev/null | grep -q "multiarch-builder"; then
if docker buildx ls | grep "multiarch-builder" | grep -q "running"; then
echo "[OK]"
else
echo "[WARN]"
fi
else
echo "[ERR]"
fi
}
get_builder_status() {
if docker buildx ls 2>/dev/null | grep -q "multiarch-builder"; then
if docker buildx ls | grep "multiarch-builder" | grep -q "running"; then
echo "[läuft]"
else
echo "[vorhanden, aber gestoppt]"
fi
else
echo "[nicht eingerichtet]"
fi
}
install_dependencies() {
whiptail --msgbox "Installation von Abhängigkeiten (Beispiel für Debian/Ubuntu). Bitte root-Rechte eingeben." 10 70
sudo apt update
sudo apt install -y docker.io git jq whiptail micro
}
install_docker_and_buildx() {
# Prüfen ob Docker installiert ist
if ! command -v docker >/dev/null 2>&1; then
whiptail --msgbox "Docker ist nicht installiert! Bitte zuerst über 'Abhängigkeiten installieren' einrichten." 10 70
return
fi
# Prüfen ob Buildx verfügbar ist
if ! docker buildx version >/dev/null 2>&1; then
whiptail --msgbox "Docker Buildx-Plugin fehlt! Installiere Buildx..." 10 70
mkdir -p ~/.docker/cli-plugins
BUILDX_URL="https://github.com/docker/buildx/releases/latest/download/buildx-$(uname -s)-$(uname -m)"
curl -sSL "$BUILDX_URL" -o ~/.docker/cli-plugins/docker-buildx
chmod +x ~/.docker/cli-plugins/docker-buildx
fi
# Prüfen, ob multiarch-builder existiert
if ! docker buildx ls | grep -q "multiarch-builder"; then
whiptail --msgbox "Richte Buildx-Builder 'multiarch-builder' ein..." 10 70
docker run --rm --privileged tonistiigi/binfmt --install all
docker buildx create --name multiarch-builder --use
docker buildx inspect --bootstrap >/dev/null 2>&1
fi
# Finalprüfung: existiert Builder jetzt wirklich?
if docker buildx ls | grep -q "multiarch-builder"; then
whiptail --msgbox "Buildx-Builder 'multiarch-builder' erfolgreich eingerichtet." 10 70
else
whiptail --msgbox "Fehler: Buildx-Builder konnte nicht eingerichtet werden!" 10 70
fi
}
set_editor() {
# editor -> paketname
declare -A editor_pkg
editor_pkg=( ["nano"]="nano" ["vim"]="vim" ["micro"]="micro" ["nvim"]="neovim" )
local options=()
declare -A editor_status
# Prüfe, ob Editor installiert ist
for cmd in "${!editor_pkg[@]}"; do
if command -v "$cmd" >/dev/null 2>&1; then
editor_status[$cmd]="(installiert)"
else
editor_status[$cmd]="(nicht installiert)"
fi
options+=("$cmd" "${editor_status[$cmd]}")
done
while true; do
choice=$(whiptail --title "Editor wählen" --menu "Bitte Editor auswählen:" 20 70 10 "${options[@]}" 3>&1 1>&2 2>&3) || return
if command -v "$choice" >/dev/null 2>&1; then
jq --arg ed "$choice" '.editor = $ed' "$GLOBAL_CONFIG" >"$GLOBAL_CONFIG.tmp" && mv "$GLOBAL_CONFIG.tmp" "$GLOBAL_CONFIG"
whiptail --msgbox "Editor wurde auf '$choice' gesetzt." 10 60
return
else
install_choice=$(whiptail --title "Editor nicht installiert" \
--yesno "Der Editor '$choice' ist nicht installiert. Möchten Sie ihn jetzt installieren?" 10 60 3>&1 1>&2 2>&3)
if [[ $? -eq 0 ]]; then
whiptail --msgbox "Installation von ${editor_pkg[$choice]}..." 8 50
sudo apt update
sudo apt install -y "${editor_pkg[$choice]}"
if command -v "$choice" >/dev/null 2>&1; then
whiptail --msgbox "$choice erfolgreich installiert." 8 50
jq --arg ed "$choice" '.editor = $ed' "$GLOBAL_CONFIG" >"$GLOBAL_CONFIG.tmp" && mv "$GLOBAL_CONFIG.tmp" "$GLOBAL_CONFIG"
return
else
whiptail --msgbox "Fehler: $choice konnte nicht installiert werden." 8 50
fi
fi
fi
done
}
# ===============================
# Projektverwaltung
# ===============================
PROJECTS_DIR="./projects"
PROJECT_CONFIG_DIR="./config/projects"
# Hauptmenü Projektverwaltung
project_menu() {
while true; do
choice=$(whiptail --title "Projektverwaltung" --menu "Bitte wählen:" 20 70 10 \
1 "Projekt erstellen" \
2 "Projekt löschen" \
3 "Projekt bearbeiten" \
0 "Zurück" \
3>&1 1>&2 2>&3) || return
case $choice in
1) create_project ;;
2) delete_project ;;
3) edit_project ;;
0) return ;;
esac
done
}
# Neues Projekt anlegen
create_project() {
project_name=$(whiptail --inputbox "Projektname eingeben:" 10 60 3>&1 1>&2 2>&3) || return
[ -z "$project_name" ] && return
mkdir -p "$PROJECT_CONFIG_DIR/$project_name" "$PROJECTS_DIR/$project_name"
# Default Config-File
cat > "$PROJECT_CONFIG_DIR/$project_name/config-file" <<EOF
# Projektkonfiguration für $project_name
registry=docker.io
image_name=$project_name
architectures=amd64
push=yes
version=1.0
latest=yes
git_repo=
EOF
# Dockerfile oder Git-Repo
if whiptail --yesno "Soll ein Git-Repo geklont werden?" 10 60; then
repo_url=$(whiptail --inputbox "Git-Repository-URL eingeben:" 10 60 3>&1 1>&2 2>&3) || return
if git clone "$repo_url" "$PROJECTS_DIR/$project_name"; then
echo "git_repo=$repo_url" >> "$PROJECT_CONFIG_DIR/$project_name/config-file"
else
whiptail --msgbox "Fehler beim Klonen des Git-Repos!" 10 60
fi
else
echo -e "FROM debian:bookworm-slim\nCMD echo 'Hello from $project_name'" > "$PROJECTS_DIR/$project_name/Dockerfile"
fi
whiptail --msgbox "Projekt $project_name wurde erstellt." 10 60
}
# Projekt löschen
delete_project() {
projects=$(ls "$PROJECT_CONFIG_DIR" 2>/dev/null)
[ -z "$projects" ] && { whiptail --msgbox "Keine Projekte vorhanden." 10 60; return; }
project=$(whiptail --menu "Projekt zum Löschen auswählen:" 20 60 10 $projects 3>&1 1>&2 2>&3) || return
if whiptail --yesno "Projekt $project wirklich löschen?" 10 60; then
rm -rf "$PROJECT_CONFIG_DIR/$project" "$PROJECTS_DIR/$project"
whiptail --msgbox "Projekt $project wurde gelöscht." 10 60
fi
}
# Projekt bearbeiten
edit_project() {
projects=$(ls "$PROJECT_CONFIG_DIR" 2>/dev/null)
[ -z "$projects" ] && { whiptail --msgbox "Keine Projekte vorhanden." 10 60; return; }
project=$(whiptail --menu "Projekt auswählen:" 20 60 10 $projects 3>&1 1>&2 2>&3) || return
local config_file="$PROJECT_CONFIG_DIR/$project/config-file"
while true; do
repo_url=$(grep "^git_repo=" "$config_file" | cut -d= -f2)
menu_items=(
1 "Registry ändern"
2 "Image-Name ändern"
3 "Architekturen setzen"
4 "Push-Option setzen"
5 "Version/Subversion ändern"
6 "Latest-Tag setzen"
7 "Projektdateien bearbeiten"
)
[ -n "$repo_url" ] && menu_items+=("8" "Git Pull")
menu_items+=("0" "Zurück")
choice=$(whiptail --title "Projekt bearbeiten: $project" \
--menu "Bitte wählen:" 20 70 12 \
"${menu_items[@]}" \
3>&1 1>&2 2>&3) || return
case $choice in
1) change_project_setting "$config_file" "registry" ;;
2) change_project_setting "$config_file" "image_name" ;;
3) change_project_setting "$config_file" "architectures" ;;
4) change_project_setting "$config_file" "push" ;;
5) change_project_setting "$config_file" "version" ;;
6) change_project_setting "$config_file" "latest" ;;
7) edit_project_files "$project" ;;
8) [ -n "$repo_url" ] && (cd "$PROJECTS_DIR/$project" && git pull || whiptail --msgbox "Git Pull fehlgeschlagen." 10 60) ;;
0) return ;;
esac
done
}
# Schlüssel im Config-File ändern
change_project_setting() {
local config_file=$1
local key=$2
local current=$(grep "^$key=" "$config_file" | cut -d= -f2)
new_value=$(whiptail --inputbox "$key ändern (aktuell: $current)" 10 60 "$current" 3>&1 1>&2 2>&3) || return
sed -i "s|^$key=.*|$key=$new_value|" "$config_file"
}
# Projektdateien bearbeiten (Dateiauswahl + Editor)
edit_project_files() {
local project=$1
local project_dir="$PROJECTS_DIR/$project"
file=$(dialog --stdout --title "Datei auswählen" --fselect "$project_dir/" 20 70) || return
if [ -f "$file" ]; then
$EDITOR_CMD "$file"
else
whiptail --msgbox "Ungültige Datei ausgewählt." 10 60
fi
}
# -------------------------
# Hauptmenü
# -------------------------
main_menu() {
while true; do
choice=$(whiptail --title "Image Builder" --menu "Bitte wählen:" 20 70 10 \
1 "Konfiguration" \
2 "Projektverwaltung" \
3 "Repository-Verwaltung" \
4 "Image-Bauen" \
5 "Image-Verwaltung" \
0 "Beenden" \
3>&1 1>&2 2>&3) || exit 0
case $choice in
1) config_menu;;
2) project_menu;;
3) whiptail --msgbox "Repository-Verwaltung (noch nicht implementiert)" 10 70;;
4) whiptail --msgbox "Image-Bauen (noch nicht implementiert)" 10 70;;
5) whiptail --msgbox "Image-Verwaltung (noch nicht implementiert)" 10 70;;
0) exit 0;;
esac
done
}
# -------------------------
# Main
# -------------------------
ensure_dirs
ensure_prereqs
main_menu