Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add upgrade-packages script #4189

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 133 additions & 0 deletions modules/salt/files/bin/upgrade-packages.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
#!/bin/bash

# Default flags
skip_confirm=false
dry_run=false
server_pattern='.*' # Default: Match all servers
include_kernel=false # Default: Exclude kernel upgrades
include_all=false # Default: Only security upgrades

# Trap SIGINT (CTRL+C) to exit the entire script
trap "echo -e '\nScript terminated by user'; exit 1" SIGINT

# Display help message
function show_help() {
echo "Usage: $0 [OPTIONS]"
echo "Options:"
echo " --yes, -y Skip confirmation prompts"
echo " --dry-run, -d Show what would be done without making changes"
echo " --servers, -s Specify target servers using a pattern"
echo " --include-kernel, -k Include kernel upgrades (requires system reboot to take effect)"
echo " --include-all, -a Include all package upgrades rather than only security upgrades (requires maintenance window)"
echo " --help, -h Show this help message"
exit 0
}

# Parse command-line arguments
while [[ $# -gt 0 ]]; do
case "$1" in
--yes|-y)
skip_confirm=true
;;
--dry-run|-d)
dry_run=true
;;
--servers|-s)
shift
server_pattern="$1"
;;
--include-kernel|-k)
include_kernel=true
;;
--include-all|-a)
include_all=true
;;
--help|-h)
show_help
;;
*)
echo "Unknown option: $1"
exit 1
;;
esac
shift
done

# Confirm before proceeding if including kernel or all upgrades
if $include_all; then
echo "WARNING: You have chosen to include all package upgrades. This type of upgrade can never be done without a maintenance window. Proceeding may cause unexpected system behavior or outage."
read -p "Are you sure you want to proceed? (yes/no): " user_confirm
if [[ "$user_confirm" != "yes" ]]; then
echo "Operation cancelled."
exit 1
fi
elif $include_kernel; then
echo "WARNING: You have chosen to include kernel upgrades. This will require a system reboot to take effect."
read -p "Are you sure you want to proceed? (yes/no): " user_confirm
if [[ "$user_confirm" != "yes" ]]; then
echo "Operation cancelled."
exit 1
fi
fi

# Get a list of target servers based on the provided pattern
servers=$(sudo salt-ssh -E "$server_pattern" test.ping --out=json | jq -r 'keys[]')

# Loop through the servers and check/execute the upgrade command
for server in $servers; do
hostname=$(echo $server | awk -F '.' '{print $1}')
echo "Checking packages for upgrade on $hostname..."

# Get the list of upgrades
if $include_all; then
packages=$(sudo salt-ssh "$server" cmd.run 'apt-get -s dist-upgrade | grep "^Inst" | awk -F " " {"print $2"}' | awk '{printf "%s ", $2}')
elif $include_kernel; then
packages=$(sudo salt-ssh "$server" cmd.run 'apt-get -s dist-upgrade | grep "^Inst" | grep -i securi | awk -F " " {"print $2"}' | awk '{printf "%s ", $2}')
else
packages=$(sudo salt-ssh "$server" cmd.run 'apt-get -s dist-upgrade | grep "^Inst" | grep -i securi | grep -v "linux-image" | awk -F " " {"print $2"}' | awk '{printf "%s ", $2}')
fi

if [ -z "${packages//[[:space:]]}" ]; then
echo "No packages to upgrade on $hostname"
else
# Create formatted package list
packages_list=$(echo $packages | sed 's/ /, /g')
packages_count=$(echo $packages | wc -w)

if [ $packages_count -gt 1 ]; then
last_package=$(echo $packages_list | awk '{print $NF}')
packages_list=$(echo $packages_list | sed "s/ $last_package$/ and $last_package/")
fi

# If dry-run mode is enabled, only display the list
if $dry_run; then
echo "[DRY RUN] Packages that would be upgraded on $hostname: $packages_list"
continue
fi

# Check if a reboot will be required before upgrading (if there are kernal upgrades)
reboot_required=$(echo "$packages" | grep -q "linux-image" && echo "yes" || echo "no")

echo "Packages that will be upgraded on $hostname: $packages_list"

# Warn about required reboot if necessary
if [[ "$reboot_required" == "yes" ]]; then
echo "WARNING: Upgrading kernel package on $hostname will require a system reboot. However, this script will not automatically perform a reboot. Please plan accordingly."
fi

# Prompt for confirmation unless --yes or -y is provided
if ! $skip_confirm; then
read -p "Are you sure you want to proceed with these upgrades? (yes/no): " upgrade_confirm
if [[ "$upgrade_confirm" != "yes" ]]; then
echo "Skipping upgrade on $hostname..."
continue
fi
fi

# Execute the upgrade command
sudo salt-ssh "$server" cmd.run "apt-get -o Dpkg::Options::='--force-confold' install --only-upgrade $packages"

# Log the packages that were upgraded
logsalmsg "Upgraded packages on $hostname: $packages_list"
fi
done
Loading