Files
Christopher 222e6af258 🔧 refactor: Use #!/usr/bin/env bash in all shell scripts (#16)
This commit refactors all the shell scripts to use `#!/usr/bin/env bash` instead of `#!/bin/bash`. This change ensures that the scripts will run with the system's default Bash interpreter, even if it is not located at the standard `/bin/bash` path.
2024-10-23 13:32:15 -05:00

205 lines
6.9 KiB
Bash

#!/usr/bin/env bash
# Define a message for branding purposes
MESSAGE="Made by BigBearTechWorld"
# Function to print a decorative line
print_decorative_line() {
# Prints a line of dashes to the console
printf "%s\n" "------------------------------------------------------"
}
# Print the introduction message with decorations
echo
print_decorative_line
echo "Portainer CE Update Script"
print_decorative_line
echo
echo "$MESSAGE"
echo
print_decorative_line
echo
echo "If this is useful, please consider supporting my work at: https://ko-fi.com/bigbeartechworld"
echo
print_decorative_line
# Function to check if a command succeeded
check_command() {
if [ $? -ne 0 ]; then
echo "Error: $1"
exit 1
fi
}
# Function to get current Portainer version
get_current_version() {
local version
# Check if Portainer container is running
if docker ps --format '{{.Names}}' | grep -q '^portainer$'; then
# Try to get version from running container
version=$(docker exec portainer portainer --version 2>/dev/null | awk '{print $2}')
# If that fails, try to get version from container labels
if [ -z "$version" ] || [ "$version" = "runtime" ]; then
version=$(docker inspect -f '{{index .Config.Labels "org.opencontainers.image.version"}}' portainer 2>/dev/null)
fi
# If still empty, get the image tag
if [ -z "$version" ]; then
version=$(docker inspect -f '{{.Config.Image}}' portainer | awk -F: '{print $2}')
[ -z "$version" ] && version="latest"
fi
else
# Check if Portainer container exists but is not running
if docker ps -a --format '{{.Names}}' | grep -q '^portainer$'; then
version=$(docker inspect -f '{{index .Config.Labels "org.opencontainers.image.version"}}' portainer 2>/dev/null)
[ -z "$version" ] && version="Unknown (container exists but is not running)"
else
# Check if Portainer image exists
if docker images portainer/portainer-ce -q | grep -q .; then
version="Unknown (image exists)"
fi
fi
fi
# If still empty, assume not installed
if [ -z "$version" ]; then
echo "Not installed"
else
echo "$version"
fi
}
# Function to get current Portainer ports
get_current_ports() {
local ports
ports=$(docker inspect --format='{{range $p, $conf := .NetworkSettings.Ports}}{{$p}}={{(index $conf 0).HostPort}} {{end}}' portainer 2>/dev/null)
echo "$ports"
}
# Function to get the last three Portainer versions
get_last_three_versions() {
curl -s https://api.github.com/repos/portainer/portainer/releases | grep -m 3 '"tag_name":' | awk -F'"' '{print $4}'
}
# Function to remove existing Portainer images
remove_existing_images() {
echo "Checking for existing Portainer images..."
existing_images=$(docker images portainer/portainer-ce -q)
if [ -n "$existing_images" ]; then
echo "Removing existing Portainer images..."
docker rmi $existing_images
check_command "Failed to remove existing Portainer images"
else
echo "No existing Portainer images found. Proceeding with installation."
fi
}
# Get current Portainer version
current_version=$(get_current_version)
# Get current Portainer ports
current_ports=$(get_current_ports)
# Set default ports if none are found
port1="8000:8000"
port2="9443:9443"
if [[ ! -z "$current_ports" ]]; then
# Extract ports from the current configuration
port1=$(echo "$current_ports" | grep -o '8000/tcp=[0-9]*' | sed 's/tcp=/:/')
port2=$(echo "$current_ports" | grep -o '9443/tcp=[0-9]*' | sed 's/tcp=/:/')
fi
# Get the last three versions
mapfile -t versions < <(get_last_three_versions)
echo "Current Portainer version: $current_version"
echo "Available versions:"
for i in "${!versions[@]}"; do
echo "$((i+1)). ${versions[i]}"
done
echo "4. Latest (${versions[0]})"
# Ask user to choose a version
# Start an infinite loop to ensure we get a valid input
while true; do
# Prompt the user to choose a version and store the input in 'choice'
read -p "Which version would you like to install? (1-4, default is 4): " choice
# If 'choice' is empty, set it to 4 (latest version)
# ${choice:-4} means "use the value of 'choice' if it's set, otherwise use 4"
choice=${choice:-4}
# Check if the input is a number between 1 and 4
# =~ is for regex matching, ^[1-4]$ matches any single digit from 1 to 4
if [[ "$choice" =~ ^[1-4]$ ]]; then
# If the choice is 4 (latest version)
if [ "$choice" -eq 4 ]; then
# Set version_to_install to the first (newest) version in the array
version_to_install=${versions[0]}
else
# Set version_to_install to the chosen version
# We subtract 1 from choice because array indexing starts at 0
version_to_install=${versions[$((choice-1))]}
fi
# Exit the loop as we have a valid choice
break
else
echo "Invalid choice. Please enter a number between 1 and 4."
fi
done
echo "You have chosen to install Portainer version: $version_to_install"
echo
echo "This script will perform the following actions:"
echo "1. Stop and remove the current Portainer container (if running)"
echo "2. Remove any existing Portainer images"
echo "3. Pull Portainer image version $version_to_install"
echo "4. Create and start a new Portainer container with version $version_to_install"
echo
read -p "Do you want to proceed with the update? (y/n): " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
echo "Update cancelled."
exit 1
fi
# Stop and remove the current Portainer container if it exists
if docker ps -a --format '{{.Names}}' | grep -q '^portainer$'; then
echo "Stopping and removing the current Portainer container..."
docker stop portainer
check_command "Failed to stop Portainer container"
docker rm portainer
check_command "Failed to remove Portainer container"
else
echo "No existing Portainer container found. Proceeding with installation."
fi
# Remove existing Portainer images
remove_existing_images
# Pull the selected Portainer image
echo "Pulling Portainer image version $version_to_install..."
docker pull portainer/portainer-ce:$version_to_install
check_command "Failed to pull Portainer image"
# Create and start a new Portainer container with the same ports
echo "Creating and starting a new Portainer container..."
docker run -d \
-p $port1 \
-p $port2 \
--name portainer \
--restart always \
-v /var/run/docker.sock:/var/run/docker.sock \
-v portainer_data:/data \
portainer/portainer-ce:$version_to_install
check_command "Failed to create and start new Portainer container"
echo "Portainer has been updated to version $version_to_install and restarted successfully."
# Verify the new version
new_version=$(get_current_version)
echo "New Portainer version: $new_version"