ab-nginx/helpers/update.sh

305 lines
9.2 KiB
Bash
Executable File

#!/bin/sh
#
# update script for ab-nginx container and utility scripts
# version 2.1.0
# script by Asif Bacchus
#
#
# functions
errMsg() {
printf "\n%s%s%s\n\n" "$err" "$1" "$norm"
[ -n "$2" ] && exit "$2" || exit 1
}
errNotify() {
printf "%s[ERROR]%s\n" "$err" "$norm"
}
okMsg() {
printf "%s%s%s\n\n" "$ok" "$1" "$norm"
}
okNotify() {
printf "%s[OK]%s\n" "$ok" "$norm"
}
makeDirectory() {
if ! [ -d "./$1" ]; then
if ! mkdir "./$1" >/dev/null 2>&1; then
errMsgString="Unable to make '$1' directory."
errMsg "$errMsgString" 40
fi
fi
}
scriptHelp() {
textNewline
textBlock "Update ${containerName} container and helper script files"
textBlock "${bold}Usage: ${localScriptName} [parameters]${norm}"
textNewline
textBlock "If run with no parameters, the script will update both the container and the helper script files, including this update script."
textBlockHeader " parameters "
textBlockParam "-h | -? | --help" "Display this help screen."
textBlockParam "-c | --container | --container-only" "Update the docker container only."
textBlockParam "-s| --scripts |--scripts-only" "Update the helper scripts (including this update script) only."
textNewline
exit 0
}
textBlock() {
printf "%s\n" "$1" | fold -w "$width" -s
}
textBlockHeader() {
printf "\n%s***%s***%s\n" "$header" "$1" "$norm"
}
textBlockParam() {
printf "%s%-35s%s%s\n" "$info" "$1" "$2" "$norm"
}
textNewline() {
printf "\n"
}
#
# text formatting presets
if command -v tput >/dev/null 2>&1; then
bold=$(tput bold)
err=$(tput bold)$(tput setaf 1)
info=$(tput bold)$(tput setaf 6)
header=$(tput bold)$(tput setaf 5)
norm=$(tput sgr0)
ok=$(tput sgr0)$(tput setaf 2)
warn=$(tput bold)$(tput setaf 3)
width=$(tput cols)
else
bold=''
err=''
info=''
header=''
norm=''
ok=''
warn=''
width=80
fi
#
# pre-requisites
# check if wget is installed
if ! command -v wget >/dev/null 2>&1; then
errMsg "Sorry, this script requires that 'wget' is installed in order to download updates. Exiting."
fi
# zero counters
updatesAvailable=0
downloadFailed=0
downloadSuccess=0
updateFailed=0
updateSuccess=0
# reference constants
dockerNamespace='nginx'
containerName='ab-nginx'
containerUpdatePath="docker.asifbacchus.dev/$dockerNamespace/$containerName:latest"
server="https://asifbacchus.dev/public/docker/$dockerNamespace/$containerName/"
checksumFilename='checksums.sha256'
# operation triggers
doDockerUpdate=1
doScriptUpdate=1
# files to update
localScriptName="$(basename "$0")"
repoScriptName='update.sh'
#
# process startup parameters
while [ $# -gt 0 ]; do
case "$1" in
-h | -\? | --help)
# display inline help
scriptHelp
;;
-s | --scripts | --scripts-only)
# update scripts only, skip docker container update
doDockerUpdate=0
;;
-c | --container | --container-only)
# update docker container only, skip script update
doScriptUpdate=0
;;
*)
printf "%s\nUnknown option: %s\n" "$err" "$1"
printf "%sUse '--help' for valid options%s\n\n" "$info" "$norm"
exit 1
;;
esac
shift
done
#
# update container
if [ "$doDockerUpdate" -eq 1 ]; then
# check if docker is installed
if ! command -v docker >/dev/null 2>&1; then
errMsg "Sorry, it appears that docker is not installed on this machine! Exiting." 2
fi
# is user root or in the docker group?
if [ ! "$(id -u)" -eq 0 ]; then
if ! id -Gn | grep docker >/dev/null; then
errMsg "You must either be root or in the 'docker' group to pull container updates." 2
fi
fi
printf "%s\n*** Updating %s container ***\n\n%s" "$info" "$containerName" "$norm"
if ! docker pull "$containerUpdatePath"; then
errMsg "There was an error updating the container. Try again later." 31
else
okMsg "Container updated!"
fi
fi
#
# update scripts
if [ "$doScriptUpdate" -eq 1 ]; then
printf "%s*** Updating %s helper scripts ***%s\n" "$info" "$containerName" "$norm"
## download latest checksums
printf "Getting latest checksums... "
if ! wget --quiet --tries=3 --timeout=10 -N "${server}${checksumFilename}"; then
errNotify
errMsg "Unable to download checksums. Try again later." 41
else
okNotify
fi
## check for updates to this script
printf "Checking for updates to this script... "
repoScriptChecksum=$(grep "$repoScriptName" "$checksumFilename" | grep -o '^\S*')
localScriptChecksum=$(sha256sum "$localScriptName" | grep -o '^\S*')
if [ "$localScriptChecksum" = "$repoScriptChecksum" ]; then
printf "[NONE]\n"
else
printf "[AVAILABLE]\n"
printf "Getting updated script... "
# download updated script
if ! wget --quiet --tries=3 --timeout=10 -O "update.sh.tmp" "${server}${repoScriptName}"; then
errNotify
# delete failed download as necessary
rm -f ./update.sh.tmp 2>/dev/null
errMsg "Unable to download script update. Try again later." 42
else
# verify download
dlScriptChecksum=$(sha256sum "update.sh.tmp" | grep -o '^\S*')
if ! [ "$dlScriptChecksum" = "$repoScriptChecksum" ]; then
printf "[ERROR]\n"
# delete corrupt download as necessary
rm -f ./update.sh.tmp 2>/dev/null
errMsg "Checksum mismatch! Try again later." 42
else
okNotify
printf "\n%s*** This script has been updated. Please re-run it to load the updated version of this file. ***%s\n\n" "$warn" "$norm"
# overwrite this script with updated script
mv -f ./update.sh.tmp "$localScriptName"
chmod +x "$localScriptName"
exit 0
fi
fi
fi
## update files
makeDirectory "config"
makeDirectory "sites"
makeDirectory "snippets"
while IFS=' ' read -r field1 field2; do
if [ "$field2" = "update.sh" ]; then continue; fi
printf "\nChecking '%s' for updates... " "$field2"
updateFilename="$field2"
repoFileChecksum="$field1"
if [ -f "$updateFilename" ]; then
localFileChecksum=$(sha256sum "$updateFilename" | grep -o '^\S*')
else
localFileChecksum=0
fi
# update file if necessary
if ! [ "$localFileChecksum" = "$repoFileChecksum" ]; then
printf "[AVAILABLE]\n"
updatesAvailable=$((updatesAvailable + 1))
# download update
printf "Downloading updated '%s'... " "$updateFilename"
if ! wget --quiet --tries=3 --timeout=10 -O "$updateFilename.tmp" "${server}${updateFilename}"; then
errNotify
downloadFailed=$((downloadFailed + 1))
# delete failed download file as necessary
rm -f "$updateFilename.tmp" 2>&1
else
okNotify
downloadSuccess=$((downloadSuccess + 1))
# verify download
printf "Verifying '%s'... " "$updateFilename"
localFileChecksum=$(sha256sum "$updateFilename.tmp" | grep -o '^\S*')
if ! [ "$localFileChecksum" = "$repoFileChecksum" ]; then
errNotify
updateFailed=$((updateFailed + 1))
# delete corrupted download file as necessary
rm -f "$updateFilename.tmp" 2>&1
else
okNotify
updateSuccess=$((updateSuccess + 1))
# overwrite old version of file
mv -f "$updateFilename.tmp" "$updateFilename"
if [ "${updateFilename##*.}" = "sh" ]; then
# shell file --> make it executable
chmod +x "$updateFilename"
fi
fi
fi
else
printf "[NONE]\n"
fi
done <"$checksumFilename"
fi
#
# display results
if [ "$doScriptUpdate" -eq 1 ]; then
printf "\n%s*** Results ***%s\n" "$info" "$norm"
printf "\tUpdates: %s available\n" "$updatesAvailable"
printf "\tDownloads: %s%s successful%s, %s%s failed%s\n" "$ok" "$downloadSuccess" "$norm" "$err" "$downloadFailed" "$norm"
printf "\tUpdates: %s%s applied%s, %s%s failed%s\n" "$ok" "$updateSuccess" "$norm" "$err" "$updateFailed" "$norm"
fi
#
# exit
if [ "$downloadFailed" -gt 0 ]; then
exit 43
elif [ "$updateFailed" -gt 0 ]; then
exit 44
else
exit 0
fi
# this is a trap for mis-coding... should never get an exit code 99!
exit 99
#
# exit return codes
# 0: normal exit, no errors
# 1: missing or invalid parameter
# 2: docker not found or no docker permissions
# 31: unable to update docker container
# 4x: helper files errors
# 40: unable to make download directories
# 41: unable to download checksums
# 42: update script: unable to download or bad checksum
# 43: update helpers: unable to download
# 44: update helpers: bad checksum, no update
# 99: coding mistake trap -- this return code should never happen!
#EOF