diff --git a/casaos-docker-compose-update/README.md b/casaos-docker-compose-update/README.md new file mode 100644 index 0000000..f7edd23 --- /dev/null +++ b/casaos-docker-compose-update/README.md @@ -0,0 +1,5 @@ +# Run command + +```bash +bash -c "$(wget -qLO - https://raw.githubusercontent.com/bigbeartechworld/big-bear-scripts/master/casaos-docker-compose-update/run.sh)" +``` diff --git a/casaos-docker-compose-update/run.sh b/casaos-docker-compose-update/run.sh new file mode 100644 index 0000000..9e2ecd0 --- /dev/null +++ b/casaos-docker-compose-update/run.sh @@ -0,0 +1,198 @@ +#!/bin/bash + +MESSAGE="Made by BigBearTechWorld" + +# Function to print a decorative line +print_decorative_line() { + printf "%s\n" "------------------------------------------------------" +} + +# Print the introduction message with decorations +echo +print_decorative_line +echo "CasaOS Docker Compose 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 + +# Check if jq is installed +if ! command -v jq &> /dev/null; then + read -p "jq is not installed. Do you want to install it? (y/N) " choice + if [[ $choice == "y" || $choice == "Y" ]]; then + sudo apt update + sudo apt install -y jq + else + echo "jq is required for this script. Exiting." + exit 1 + fi +fi + +# Check if yq is installed +if ! command -v yq &> /dev/null; then + read -p "yq is not installed. Do you want to install it? (y/N) " choice + if [[ $choice == "y" || $choice == "Y" ]]; then + # Determine system architecture + ARCH=$(uname -m) + if [[ "$ARCH" == "x86_64" ]]; then + BINARY="yq_linux_amd64" + elif [[ "$ARCH" == "aarch64" ]]; then + BINARY="yq_linux_arm64" + else + echo "Unsupported architecture. Exiting." + exit 1 + fi + + # Fetch the latest version of yq + VERSION=$(curl -s https://api.github.com/repos/mikefarah/yq/releases/latest | jq -r '.tag_name') + + # Download and install yq + wget "https://github.com/mikefarah/yq/releases/download/${VERSION}/${BINARY}.tar.gz" -O - |\ + tar xz && sudo mv ${BINARY} /usr/bin/yq + else + echo "yq is required for this script. Exiting." + exit 1 + fi +fi + +# Check if skopeo is installed +if ! command -v skopeo &> /dev/null; then + read -p "skopeo is not installed. Do you want to install it? (y/N) " choice + if [[ $choice == "y" || $choice == "Y" ]]; then + sudo apt update + sudo apt install -y skopeo + else + echo "skopeo is required for this script. Exiting." + exit 1 + fi +fi + +# Function to compare semantic version numbers +compare_versions() { + # Extract numeric part and suffix (if exists) from version strings + VER1_NUMERIC=$(echo "$1" | sed -E 's/([0-9.]+).*/\1/') + VER1_SUFFIX=$(echo "$1" | sed -E 's/[0-9.]+//') + VER2_NUMERIC=$(echo "$2" | sed -E 's/([0-9.]+).*/\1/') + VER2_SUFFIX=$(echo "$2" | sed -E 's/[0-9.]+//') + + IFS='.' read -ra NUM1 <<< "$VER1_NUMERIC" + IFS='.' read -ra NUM2 <<< "$VER2_NUMERIC" + + for i in "${!NUM1[@]}"; do + if [[ -z "${NUM2[i]}" ]]; then + NUM2[i]=0 + fi + + # Ensure the segments are numeric before comparing + if [[ "${NUM1[i]}" =~ ^[0-9]+$ && "${NUM2[i]}" =~ ^[0-9]+$ ]]; then + if ((10#${NUM1[i]} > 10#${NUM2[i]})); then + return 0 + elif ((10#${NUM1[i]} < 10#${NUM2[i]})); then + return 1 + fi + fi + done + + # If numeric parts are the same, compare the suffixes + if [[ "$VER1_SUFFIX" > "$VER2_SUFFIX" ]]; then + return 0 + elif [[ "$VER1_SUFFIX" < "$VER2_SUFFIX" ]]; then + return 1 + fi + + return 2 +} + +BASE_DIR="/var/lib/casaos/apps" + +# Loop through all directories in BASE_DIR +for DIR in $BASE_DIR/*/; do + + # Construct the path to the Docker Compose file in the current directory + FILE="${DIR}docker-compose.yml" + + if [[ -f $FILE ]]; then + SERVICE_NAME=$(yq eval '.name' $FILE) + FULL_IMAGE_NAME=$(yq eval '.services.*.image' $FILE) + IMAGE_NAME=$(echo $FULL_IMAGE_NAME | cut -d':' -f1) + CURRENT_TAG=$(echo $FULL_IMAGE_NAME | cut -d':' -f2) + + # Fetch tags containing numbers for the image using skopeo + ALL_TAGS=$(skopeo list-tags docker://$IMAGE_NAME | jq -r '.Tags[]' | grep '[0-9]') + + # Sort tags using version sort and reverse the order to have latest first + SORTED_TAGS=$(echo "$ALL_TAGS" | sort -Vr) + + # Extract version and variant from current tag + CURRENT_VERSION=$(echo $CURRENT_TAG | grep -oE '^[0-9]+\.[0-9]+\.[0-9]+') + CURRENT_VARIANT=$(echo $CURRENT_TAG | sed "s/$CURRENT_VERSION//") + + # Get the latest 30 tags + NUMERIC_TAGS=$(echo "$SORTED_TAGS" | grep -E '^[0-9]+\.[0-9]+\.[0-9]+.*' | head -n 30) + + LATEST_NUMERIC_TAG_WITH_VARIANT="" + LATEST_NUMERIC_TAG="" + for TAG in $NUMERIC_TAGS; do + if [[ "$TAG" == *"$CURRENT_VARIANT"* ]]; then + LATEST_NUMERIC_TAG_WITH_VARIANT="$TAG" + LATEST_NUMERIC_TAG="${TAG%%$CURRENT_VARIANT}" + fi + + # Check if both tags have been found and exit the loop + if [[ -n "$LATEST_NUMERIC_TAG_WITH_VARIANT" && -n "$LATEST_NUMERIC_TAG" ]]; then + break + fi + done + + # If the Docker Compose file uses the 'latest' tag + if [[ "$CURRENT_TAG" == "latest" ]]; then + read -p "The image $IMAGE_NAME is using the 'latest' tag. Do you want to switch to a specific tag? (y/N) " choice + if [[ $choice == "y" || $choice == "Y" ]]; then + echo "Available numeric tags for $IMAGE_NAME:" + select TAG in $NUMERIC_TAGS; do + if [[ -n $TAG ]]; then + yq eval -i ".services.*.image = \"$IMAGE_NAME:$TAG\"" $FILE + echo "Updated $FILE with tag $TAG" + + # Run the casaos-cli command + casaos-cli app-management apply $SERVICE_NAME --file=/var/lib/casaos/apps/$SERVICE_NAME/docker-compose.yml + echo "Applying changes to $SERVICE_NAME..." + break + else + echo "Invalid choice. Try again." + fi + done + else + echo "Skipping $IMAGE_NAME..." + fi + # If the Docker Compose file uses a specific tag + else + compare_versions "$CURRENT_TAG" "$LATEST_NUMERIC_TAG" + RESULT=$? + if [[ $RESULT -eq 1 ]]; then + echo "Current tag for $IMAGE_NAME is $CURRENT_TAG. Newer numeric tags available:" + select TAG in $NUMERIC_TAGS; do + if [[ -n $TAG ]]; then + yq eval -i ".services.*.image = \"$IMAGE_NAME:$TAG\"" $FILE + echo "Updated $FILE with tag $TAG" + + # Run the casaos-cli command + casaos-cli app-management apply $SERVICE_NAME --file=/var/lib/casaos/apps/$SERVICE_NAME/docker-compose.yml + echo "Applying changes to $SERVICE_NAME..." + break + else + echo "Invalid choice. Try again." + fi + done + else + echo "The image $IMAGE_NAME is up-to-date with the tag $CURRENT_TAG." + fi + fi + fi + +done