#!/bin/bash set -euo pipefail # Log function log() { echo "[APT-WRAPPER] $1" } # Function to add repository files add_repos() { local repos_config="$1" local cleanup=false # Check if cleanup is enabled if echo "$repos_config" | jq -e '.cleanup' >/dev/null 2>&1; then cleanup=$(echo "$repos_config" | jq -r '.cleanup') fi # Add repository files if echo "$repos_config" | jq -e '.files' >/dev/null 2>&1; then local files=$(echo "$repos_config" | jq -r '.files[]? // empty') for file in $files; do if [[ $file == http* ]]; then log "Downloading repository file: $file" curl -fsSL "$file" -o "/etc/apt/sources.list.d/$(basename "$file")" else log "Copying repository file: $file" cp "$file" "/etc/apt/sources.list.d/" fi done fi # Add PPA repositories if echo "$repos_config" | jq -e '.ppa' >/dev/null 2>&1; then local ppas=$(echo "$repos_config" | jq -r '.ppa[]? // empty') for ppa in $ppas; do log "Adding PPA: $ppa" add-apt-repository -y "$ppa" done fi # Add GPG keys if echo "$repos_config" | jq -e '.keys' >/dev/null 2>&1; then local keys=$(echo "$repos_config" | jq -r '.keys[]? // empty') for key in $keys; do if [[ $key == http* ]]; then log "Downloading and adding GPG key: $key" curl -fsSL "$key" | apt-key add - else log "Adding GPG key: $key" apt-key add "$key" fi done fi # Enable backports if requested if echo "$repos_config" | jq -e '.backports' >/dev/null 2>&1; then local backports=$(echo "$repos_config" | jq -r '.backports') if [ "$backports" = "true" ]; then log "Enabling backports repository" echo "deb http://deb.debian.org/debian $(lsb_release -cs)-backports main" > /etc/apt/sources.list.d/backports.list fi fi # Update package lists log "Updating package lists" apt-get update # Clean up repositories if requested if [ "$cleanup" = "true" ]; then log "Cleaning up added repositories" rm -f /etc/apt/sources.list.d/*.list apt-get update fi } # Function to handle /opt/ symlinking handle_optfix() { local optfix_config="$1" if [ -n "$optfix_config" ]; then local optfixes=$(echo "$optfix_config" | jq -r '.[]? // empty') for optfix in $optfixes; do log "Setting up /opt/ symlink for: $optfix" mkdir -p "/opt/$optfix" ln -sf "/opt/$optfix" "/usr/local/$optfix" done fi } # Function to install packages install_packages() { local install_config="$1" local skip_unavailable=false # Check if skip-unavailable is enabled if echo "$install_config" | jq -e '.skip-unavailable' >/dev/null 2>&1; then skip_unavailable=$(echo "$install_config" | jq -r '.skip-unavailable') fi # Install packages if echo "$install_config" | jq -e '.packages' >/dev/null 2>&1; then local packages=$(echo "$install_config" | jq -r '.packages[]? // empty') for package in $packages; do if echo "$package" | jq -e '.repo' >/dev/null 2>&1; then # Package from specific repository local repo=$(echo "$package" | jq -r '.repo') local repo_packages=$(echo "$package" | jq -r '.packages[]? // empty') for repo_package in $repo_packages; do log "Installing $repo_package from repository $repo" apt-get install -y "$repo_package" || { if [ "$skip_unavailable" = "true" ]; then log "WARNING: Package $repo_package not available, skipping" else log "ERROR: Failed to install package $repo_package" exit 1 fi } done else # Direct package specification if [[ $package == http* && $package == *.deb ]]; then log "Downloading and installing .deb package: $package" curl -fsSL "$package" -o /tmp/package.deb dpkg -i /tmp/package.deb || apt-get install -f -y rm -f /tmp/package.deb else log "Installing package: $package" apt-get install -y "$package" || { if [ "$skip_unavailable" = "true" ]; then log "WARNING: Package $package not available, skipping" else log "ERROR: Failed to install package $package" exit 1 fi } fi fi done fi } # Function to remove packages remove_packages() { local remove_config="$1" if echo "$remove_config" | jq -e '.packages' >/dev/null 2>&1; then local packages=$(echo "$remove_config" | jq -r '.packages[]? // empty') for package in $packages; do log "Removing package: $package" apt-get remove -y "$package" || { log "WARNING: Failed to remove package $package" } done fi } # Function to replace packages replace_packages() { local replace_config="$1" if echo "$replace_config" | jq -e '.[]' >/dev/null 2>&1; then local replacements=$(echo "$replace_config" | jq -c '.[]') echo "$replacements" | while read -r replacement; do local from_repo=$(echo "$replacement" | jq -r '.from-repo // empty') local packages=$(echo "$replacement" | jq -r '.packages[]? // empty') local skip_unavailable=$(echo "$replacement" | jq -r '.skip-unavailable // false') log "Replacing packages from repository: $from_repo" for package in $packages; do log "Replacing package: $package" apt-get install -y "$package" || { if [ "$skip_unavailable" = "true" ]; then log "WARNING: Package $package not available, skipping" else log "ERROR: Failed to replace package $package" exit 1 fi } done done fi } # Function to install task packages install_tasks() { local task_config="$1" if echo "$task_config" | jq -e '.packages' >/dev/null 2>&1; then local with_optional=$(echo "$task_config" | jq -r '.with-optional // false') local packages=$(echo "$task_config" | jq -r '.packages[]? // empty') for task in $packages; do log "Installing task: $task" if [ "$with_optional" = "true" ]; then tasksel install "$task" || { log "WARNING: Failed to install task $task" } else tasksel install "$task" || { log "WARNING: Failed to install task $task" } fi done fi } # Function to remove task packages remove_tasks() { local task_config="$1" if echo "$task_config" | jq -e '.packages' >/dev/null 2>&1; then local packages=$(echo "$task_config" | jq -r '.packages[]? // empty') for task in $packages; do log "Removing task: $task" tasksel remove "$task" || { log "WARNING: Failed to remove task $task" } done fi } # Main execution main() { local module_config="$1" log "Starting apt module execution" # Handle repositories if echo "$module_config" | jq -e '.repos' >/dev/null 2>&1; then log "Processing repositories configuration" add_repos "$(echo "$module_config" | jq -c '.repos')" fi # Handle /opt/ symlinking if echo "$module_config" | jq -e '.optfix' >/dev/null 2>&1; then log "Processing optfix configuration" handle_optfix "$(echo "$module_config" | jq -c '.optfix')" fi # Handle package installation if echo "$module_config" | jq -e '.install' >/dev/null 2>&1; then log "Processing package installation" install_packages "$(echo "$module_config" | jq -c '.install')" fi # Handle package removal if echo "$module_config" | jq -e '.remove' >/dev/null 2>&1; then log "Processing package removal" remove_packages "$(echo "$module_config" | jq -c '.remove')" fi # Handle package replacement if echo "$module_config" | jq -e '.replace' >/dev/null 2>&1; then log "Processing package replacement" replace_packages "$(echo "$module_config" | jq -c '.replace')" fi # Handle task installation if echo "$module_config" | jq -e '.task-install' >/dev/null 2>&1; then log "Processing task installation" install_tasks "$(echo "$module_config" | jq -c '.task-install')" fi # Handle task removal if echo "$module_config" | jq -e '.task-remove' >/dev/null 2>&1; then log "Processing task removal" remove_tasks "$(echo "$module_config" | jq -c '.task-remove')" fi # Clean up log "Cleaning up package cache" apt-get clean apt-get autoremove -y log "apt module execution completed successfully" } # Execute main function with the module configuration main "$1"