453 lines
14 KiB
Bash
Executable File
453 lines
14 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
|
|
}
|
|
|
|
load_global_config() {
|
|
if [[ -f "$GLOBAL_CONFIG" ]]; then
|
|
EDITOR_CMD=$(jq -r '.editor // "nano"' "$GLOBAL_CONFIG")
|
|
else
|
|
EDITOR_CMD="nano"
|
|
fi
|
|
}
|
|
|
|
ensure_dirs
|
|
load_global_config
|
|
|
|
# -------------------------
|
|
# 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
|
|
# Speziell für nano: Syntax-Highlighting installieren
|
|
if [[ "$choice" == "nano" ]]; then
|
|
NANO_DIR="$HOME/.nano"
|
|
NANORC="$HOME/.nanorc"
|
|
if [[ -d "$NANO_DIR/.git" ]]; then
|
|
git -C "$NANO_DIR" pull --quiet
|
|
else
|
|
git clone https://github.com/scopatz/nanorc.git "$NANO_DIR"
|
|
fi
|
|
if ! grep -q "include $NANO_DIR" "$NANORC" 2>/dev/null; then
|
|
{
|
|
echo "## nano syntax highlighting"
|
|
echo "include $NANO_DIR/*.nanorc"
|
|
} >> "$NANORC"
|
|
fi
|
|
fi
|
|
|
|
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; }
|
|
|
|
menu_list=()
|
|
for p in $projects; do
|
|
menu_list+=("$p" "")
|
|
done
|
|
|
|
project=$(whiptail --menu "Projekt zum Löschen auswählen:" 20 60 10 "${menu_list[@]}" 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; }
|
|
|
|
# Projekte für Menü vorbereiten (immer 2 Spalten)
|
|
menu_list=()
|
|
for p in $projects; do
|
|
menu_list+=("$p" "")
|
|
done
|
|
|
|
project=$(whiptail --menu "Projekt auswählen:" 20 60 10 "${menu_list[@]}" 3>&1 1>&2 2>&3) || return
|
|
local config_file="$PROJECT_CONFIG_DIR/$project/config-file"
|
|
local project_dir="$PROJECTS_DIR/$project"
|
|
|
|
while true; do
|
|
repo_url=$(grep "^git_repo=" "$config_file" | cut -d= -f2)
|
|
|
|
menu_items=(
|
|
1 "Registries auswählen"
|
|
2 "Architekturen auswählen"
|
|
3 "Push aktivieren/deaktivieren"
|
|
4 "Latest-Tag setzen/entfernen"
|
|
5 "Version/Subversion ändern"
|
|
6 "Automatische Subversion"
|
|
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) edit_project_registries "$config_file" ;;
|
|
2) edit_project_architectures "$config_file" ;;
|
|
3) edit_project_push "$config_file" ;;
|
|
4) edit_project_latest "$config_file" ;;
|
|
5) change_project_setting "$config_file" "version" ;;
|
|
6) edit_project_auto_subversion "$config_file" ;;
|
|
7) edit_project_files "$project" ;;
|
|
8) [ -n "$repo_url" ] && (cd "$project_dir" && 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"
|
|
}
|
|
|
|
# Aktuellen Editor aus global/config.json holen
|
|
# Aktuellen Editor aus global/config.json holen
|
|
get_editor_cmd() {
|
|
if [[ -f "$GLOBAL_CONFIG" ]]; then
|
|
jq -r '.editor // "nano"' "$GLOBAL_CONFIG"
|
|
else
|
|
echo "nano"
|
|
fi
|
|
}
|
|
|
|
# Projektdateien bearbeiten (Dateiauswahl + Editor)
|
|
edit_project_files() {
|
|
local project=$1
|
|
local project_dir="$PROJECTS_DIR/$project"
|
|
|
|
# Prüfen ob Projektordner existiert
|
|
if [[ ! -d "$project_dir" ]]; then
|
|
whiptail --msgbox "Projektordner nicht gefunden." 10 60
|
|
return
|
|
fi
|
|
|
|
# Prüfen ob der Ordner Dateien enthält
|
|
if [[ -z $(find "$project_dir" -type f | head -n 1) ]]; then
|
|
whiptail --msgbox "Keine Dateien im Projektordner vorhanden." 10 60
|
|
return
|
|
fi
|
|
|
|
# Datei auswählen
|
|
if ! file=$(whiptail --title "Datei auswählen" --fselect "$project_dir/" 20 70 3>&1 1>&2 2>&3); then
|
|
return
|
|
fi
|
|
|
|
[[ -z "$file" ]] && return
|
|
|
|
# Editor aus globaler Config holen
|
|
local editor_cmd
|
|
editor_cmd=$(get_editor_cmd)
|
|
|
|
# Datei im Editor öffnen
|
|
"$editor_cmd" "$file"
|
|
}
|
|
|
|
edit_project_architectures() {
|
|
local config_file=$1
|
|
local current=$(grep "^architectures=" "$config_file" | cut -d= -f2 | tr ',' ' ')
|
|
local all_archs=("amd64" "arm64" "armhf" "x86")
|
|
menu_list=()
|
|
for a in "${all_archs[@]}"; do
|
|
if [[ " $current " =~ " $a " ]]; then
|
|
menu_list+=("$a" "$a" ON)
|
|
else
|
|
menu_list+=("$a" "$a" OFF)
|
|
fi
|
|
done
|
|
selected=$(whiptail --title "Architekturen auswählen" --checklist "Mehrere auswählen" 20 70 10 "${menu_list[@]}" 3>&1 1>&2 2>&3) || return
|
|
selected=$(echo $selected | tr -d '"')
|
|
sed -i "s|^architectures=.*|architectures=$selected|" "$config_file"
|
|
}
|
|
|
|
edit_project_push() {
|
|
local config_file=$1
|
|
local current=$(grep "^push=" "$config_file" | cut -d= -f2)
|
|
local value="OFF"
|
|
[ "$current" == "yes" ] && value="ON"
|
|
selected=$(whiptail --title "Push aktivieren?" --checklist "Push auswählen" 10 50 1 push "Push aktivieren" $value 3>&1 1>&2 2>&3) || return
|
|
[[ $selected == *push* ]] && val="yes" || val="no"
|
|
sed -i "s|^push=.*|push=$val|" "$config_file"
|
|
}
|
|
|
|
edit_project_latest() {
|
|
local config_file=$1
|
|
local current=$(grep "^latest=" "$config_file" | cut -d= -f2)
|
|
local value="OFF"
|
|
[ "$current" == "yes" ] && value="ON"
|
|
selected=$(whiptail --title "Latest-Tag setzen?" --checklist "Latest auswählen" 10 50 1 latest "Latest setzen" $value 3>&1 1>&2 2>&3) || return
|
|
[[ $selected == *latest* ]] && val="yes" || val="no"
|
|
sed -i "s|^latest=.*|latest=$val|" "$config_file"
|
|
}
|
|
|
|
edit_project_auto_subversion() {
|
|
local config_file=$1
|
|
local current=$(grep "^auto_subversion=" "$config_file" | cut -d= -f2)
|
|
local value="OFF"
|
|
[ "$current" == "yes" ] && value="ON"
|
|
selected=$(whiptail --title "Subversion automatisch erhöhen?" --checklist "Auto Subversion auswählen" 10 50 1 auto "Automatisch erhöhen" $value 3>&1 1>&2 2>&3) || return
|
|
[[ $selected == *auto* ]] && val="yes" || val="no"
|
|
# falls auto_subversion key nicht existiert, hinzufügen
|
|
if grep -q "^auto_subversion=" "$config_file"; then
|
|
sed -i "s|^auto_subversion=.*|auto_subversion=$val|" "$config_file"
|
|
else
|
|
echo "auto_subversion=$val" >> "$config_file"
|
|
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
|