Dotfiles/setup/modules/FreeipaAnsible/ansible/ansipa-install-packages.sh

135 lines
3.9 KiB
Bash

#!/usr/bin/env bash
set -e
PREFIX="dev_pkg_"
STATE_FILE="/var/lib/ansipa-packages/installed.list"
mkdir -p "$(dirname "$STATE_FILE")"
# Detect distro
if [ -f /etc/os-release ]; then
. /etc/os-release
DISTRO=$ID
else
DISTRO="unknown"
fi
# -----------------------------
# Package install function
# -----------------------------
install_pkg() {
PKG="$1"
case "$DISTRO" in
arch)
pacman -Sy --noconfirm "$PKG" 2>/dev/null || true
;;
debian|ubuntu)
apt update -y && apt install -y "$PKG" 2>/dev/null || true
;;
rhel|centos|rocky|almalinux)
yum install -y "$PKG" 2>/dev/null || dnf install -y "$PKG" 2>/dev/null || true
;;
fedora)
dnf install -y "$PKG" 2>/dev/null || true
;;
opensuse*|sles)
zypper install -y "$PKG" 2>/dev/null || true
;;
esac
}
# -----------------------------
# Package uninstall function
# -----------------------------
remove_pkg() {
PKG="$1"
case "$DISTRO" in
arch)
pacman -Rns --noconfirm "$PKG" 2>/dev/null || true
;;
debian|ubuntu)
apt remove -y "$PKG" 2>/dev/null || true
;;
rhel|centos|rocky|almalinux)
yum remove -y "$PKG" 2>/dev/null || dnf remove -y "$PKG" 2>/dev/null || true
;;
fedora)
dnf remove -y "$PKG" 2>/dev/null || true
;;
opensuse*|sles)
zypper remove -y "$PKG" 2>/dev/null || true
;;
esac
}
# -----------------------------
# Get FreeIPA install groups
# -----------------------------
IPA_GROUPS=$(ipa group-find --pkey-only | awk '/Group name:/{print $NF}' | grep "^$PREFIX" || true)
# Extract package names from groups
DESIRED_PKGS=()
for G in $IPA_GROUPS; do
PKG="${G#$PREFIX}"
DESIRED_PKGS+=("$PKG")
done
# -----------------------------
# Get currently installed packages
# -----------------------------
case "$DISTRO" in
arch)
INSTALLED_PKGS=$(pacman -Qq)
;;
debian|ubuntu)
INSTALLED_PKGS=$(dpkg -l | awk '/^ii/ {print $2}')
;;
rhel|centos|rocky|almalinux|fedora)
INSTALLED_PKGS=$(rpm -qa --qf "%{NAME}\n")
;;
opensuse*|sles)
INSTALLED_PKGS=$(rpm -qa --qf "%{NAME}\n")
;;
*)
INSTALLED_PKGS=""
;;
esac
# -----------------------------
# Install missing packages and record them
# -----------------------------
[[ -f "$STATE_FILE" ]] || touch "$STATE_FILE"
for PKG in "${DESIRED_PKGS[@]}"; do
if ! echo "$INSTALLED_PKGS" | grep -qx "$PKG"; then
echo "[INFO] Installing package: $PKG"
install_pkg "$PKG"
fi
# Record that ansipa manages this package
grep -qxF "$PKG" "$STATE_FILE" || echo "$PKG" >> "$STATE_FILE"
done
# -----------------------------
# Remove packages no longer desired
# Only remove packages previously installed by ansipa (tracked in state file).
# -----------------------------
while IFS= read -r PKG; do
[[ -z "$PKG" ]] && continue
# Still desired? Leave it alone.
if printf '%s\n' "${DESIRED_PKGS[@]+"${DESIRED_PKGS[@]}"}" | grep -qxF "$PKG"; then
continue
fi
echo "[INFO] Removing package no longer required by any IPA group: $PKG"
remove_pkg "$PKG"
# Remove from state file
grep -vxF "$PKG" "$STATE_FILE" > "${STATE_FILE}.tmp" && mv "${STATE_FILE}.tmp" "$STATE_FILE"
done < "$STATE_FILE"
# Persist current desired list (union of what's already tracked + newly added)
if [[ ${#DESIRED_PKGS[@]} -gt 0 ]]; then
printf '%s\n' "${DESIRED_PKGS[@]}" | sort -u > "${STATE_FILE}.tmp"
# Merge: keep previously-managed packages that are still desired
sort -u "$STATE_FILE" "${STATE_FILE}.tmp" > "${STATE_FILE}.merged"
comm -12 "${STATE_FILE}.merged" "${STATE_FILE}.tmp" > "$STATE_FILE"
rm -f "${STATE_FILE}.tmp" "${STATE_FILE}.merged"
fi