Compare commits

...

3 Commits

3 changed files with 152 additions and 16 deletions

119
HatarashiHako Executable file
View File

@@ -0,0 +1,119 @@
#!/bin/bash
##Script to update Docker container images occasionally and alert when update is done.
source /root/.bash_profile
if [[ $1 =~ "-v|--verbose|verbose" ]]; then
source /home/shmick/Scripts/Okiru "$1"
else
source /home/shmick/Scripts/Okiru
fi
source /etc/environment
#Remember where you are to change back to later
LOCAL_DIR=`pwd`
#This is where containers live
CONTAINER_DIR="/var/Red-Vol/Media/Containers/"
declare -a CONTAINER_PATHS
declare -a OUTDATED_CONTAINERS
declare -a FAILED_CONTAINERS
declare -a UPDATED_CONTAINERS
#Remove log from last runs, if present
if [[ -f /tmp/docker-updated ]]; then
rm /tmp/docker-updated
fi
#Start counting how many containers fail; appears in final mail subject.
OUTDATED_COUNT="0"
CONTAINER_PATHS=$(find $CONTAINER_DIR -maxdepth 2 -type f -name docker-compose.yml ! -path '*Archive*' | xargs dirname )
#Find containers in ^ base dir ^ in base container path ^ by finding compose files ^ (not here) ^ and getting their directory name.
for container_path in ${CONTAINER_PATHS[@]}; do
cd $container_path
debug "Working on container directory $container_path"
container_stack=$(basename $container_path)
info "Working on stack" "$container_stack"
container_images="$(cat $container_path/docker-compose.yml | grep -E "image: ([a-z]+)/([a-z]+)(:[a-z0-9].*$)?" | grep -Ev 'postgresql|mariadb' | awk '{print $2}')"
# search for a pattern of something:something with optional :tag ^ avoid database containers print ^ image name
for container_image in $container_images; do
container_name="$(echo $container_image | awk -F/ '{print $2}' | sed "s/\:.*//")"
# remove everything after the : ^
debug "$container_stack has image $container_image"
if [[ -n $(echo $container_image | grep -E "(.*:[a-z0-9].*$)") ]]; then
# check if there is a :tag present ^
image_tag=":$(echo $container_image | awk -F: '{print $NF}')"
# !! Add : ^ before image !! so it is only added to later commands if there is an image at all
debug "$container_image has tag $image_tag"
export container_image=$(echo $container_image | awk -F: '{print $1}')
# If the container does have a tag, keep the base name ^ without it (before the :)
fi
debug "Fetching local image checksum with: docker inspect \"$container_image$image_tag\" | grep -Eo \"$container_image@sha256:([0-9a-zA-Z].*)(\")\" | sed -e 's/\"//g' | awk -F@ '{print \$2}"
local_image=$(docker inspect "$container_image$image_tag" | grep -Eo "$container_image@sha256:([0-9a-zA-Z].*)(\")" | sed -e 's/"//g' -e 's/\s+//g' | awk -F@ '{print $2}')
# remember, this bit ^ is empty without an image ^ this is the main image checksum remove ^ " and whitespace and^ get the checksum after the @
if [[ -z $local_image ]]; then
error "Error fetching local image checksum for container $container_name!"
#The script will complain about failed containers later on
FAILED_CONTAINERS+=("(local) $container_name")
continue 2
else
debug "Local SHA256 for $container_image is $local_image"
fi
debug "Fetching remote image with: skopeo inspect --creds \"dkd6:Vulthuryol569\" docker://docker.io/$container_image$image_tag | grep Digest | head -1 | grep -Eo 'sha256:([0-9a-zA-Z].*)(\")' | sed -e 's/\"//g'"
#Use Skopeo, a Red Hat tool, with my Docker Hub account to register the remote image checksum
remote_image=$(skopeo inspect --creds "dkd6:Vulthuryol569" docker://docker.io/$container_image$image_tag | grep Digest | head -1 | grep -Eo 'sha256:([0-9a-zA-Z].*)(")' | sed -e 's/"//g' -e 's/\s+//g' )
#Sometimes; Docker hub hangs up; try again if you failed
if [[ -z $remote_image ]]; then
remote_image=$(skopeo inspect --creds "dkd6:Vulthuryol569" docker://docker.io/$container_image$image_tag | grep Digest | head -1 | grep -Eo 'sha256:([0-9a-zA-Z].*)(")' | sed -e 's/"//g')
fi
#Now, if you still don't have an image after the second try, something's fuckey.
if [[ -z $remote_image ]]; then
error "Error fetching remote image checksum for container $container_name!"
FAILED_CONTAINERS+=("(remote) $container_name")
continue 2
else
debug "Remote SHA256 for $container_image is $remote_image"
fi
#If we have both checksums, compare them; they should be identical, or the container is outdated.
if [[ -n $local_image ]] && [[ -n $remote_image ]] && [[ "$local_image" =~ "$remote_image" ]]; then
ok "$container_name is up to date!"
else
warn "$container_name is out of date!"
info "Attempting to update $container_name"
if docker-compose pull $container_name; then
info "Pulled latest image for $container_name succesfully. Restarting..."
if docker-compose up -d --remove-orphans; then
ok "$container_stack has been updated sucessfully!"
UPDATED_CONTAINERS+=("($container_stack) $container_name")
else
error "Failed to update $container_name!"
FAILED_CONTAINERS+=("($container_stack|update) $container_name")
#Add to array for mail report
OUTDATED_CONTAINERS+=("($container_stack) $container_name")
export OUTDATED_COUNT=$(($OUTDATED_COUNT+1))
fi
else
error "Failed to pull image for $container_name!"
FAILED_CONTAINERS+=("($container_stack|pull) $container_name")
#Add to array for mail report
OUTDATED_CONTAINERS+=("($container_stack) $container_name")
export OUTDATED_COUNT=$(($OUTDATED_COUNT+1))
fi
fi
#If you found an image tag, reset it before moving on to another container
image_tag=""
done
cd $LOCAL_DIR
done
echo "All done!"
#Iterate over the arrays and output results to a file; if needed, it will be neatly mailed.
if [[ ${#OUTDATED_CONTAINERS[@]} != 0 ]] || [[ ${#FAILED_CONTAINERS[@]} != 0 ]] || [[ ${#UPDATED_CONTAINERS[@]} != 0 ]]; then
if [[ ${#UPDATED_CONTAINERS[@]} != 0 ]]; then
printf "The following containers have updated succefully:\n" > /tmp/docker-updated
printf "%s\n" "${UPDATED_CONTAINERS[@]}" >> /tmp/docker-updated
fi
if [[ ${#OUTDATED_CONTAINERS[@]} != 0 ]]; then
printf "The following containers are out of date:\n" >> /tmp/docker-updated
printf "%s\n" "${OUTDATED_CONTAINERS[@]}" >> /tmp/docker-updated
fi
if [[ ${#FAILED_CONTAINERS[@]} != 0 ]]; then
printf "The following containers failed the update process:\n" >> /tmp/docker-updated
printf "%s\n" "${FAILED_CONTAINERS[@]}" >> /tmp/docker-updated
fi
cat /tmp/docker-updated | mail -s "Docker containers update report - `date +"%B %d %Y"`" -r "Takahe@pukeko.xyz" matanhorovitz@protonmail.com
rm /tmp/docker-updated
fi

View File

@@ -91,7 +91,7 @@ backup(){
if safety "$REPOSITORY"; then if safety "$REPOSITORY"; then
#Run the backup #Run the backup
info "Backing up repository $REPOSITORY" info "Backing up repository $REPOSITORY"
if restic -r b2:"$REPOSITORY" backup "$REPOSITORY_PATH" --limit-upload="$BWLIMIT" --limit-download="$BWLIMIT" | tee -a $LOG; then if restic --cache-dir="$RESTIC_CACHE_DIR" -r b2:"$REPOSITORY" backup "$REPOSITORY_PATH" --limit-upload="$BWLIMIT" --limit-download="$BWLIMIT" | tee -a $LOG; then
ok "Path $REPOSITORY_PATH completed upload to $REPOSITORY." ok "Path $REPOSITORY_PATH completed upload to $REPOSITORY."
check "$REPOSITORY" check "$REPOSITORY"
else else
@@ -175,5 +175,6 @@ elif [[ -n $CLEAN ]] || [[ $(date +%a) == "Friday" ]]; then
clean Pukeko-XYZ-Cloud clean Pukeko-XYZ-Cloud
fi fi
#Wrap up this run's log and report nicely #Wrap up this run's log and report nicely
echo "All done; have a nice day!"
end_logging end_logging
exit 0 exit 0

46
Okiru
View File

@@ -31,6 +31,9 @@ WHITE='\033[0;37m'
GRAY='\033[1;37m' GRAY='\033[1;37m'
STOP="\e[0m" STOP="\e[0m"
#If passed from calling script, run in verbose mode (enables debug logging level)
VERBOSE="$1"
#If a function calls 'logging' for a log, it will create a log file; otherwise, keep the #If a function calls 'logging' for a log, it will create a log file; otherwise, keep the
#+variable empty thus printing only to terminal #+variable empty thus printing only to terminal
@@ -76,37 +79,50 @@ logging () {
printf "Logging is ${RED}disabled${STOP}; No log file will be generated.\n" printf "Logging is ${RED}disabled${STOP}; No log file will be generated.\n"
fi fi
} }
#Debugging level logging; can be toggled via a switch #If VERBOSE mode is enabled, print debug messages
debug () { if [[ -n $VERBOSE ]]; then
printf "${BLUE}[DEBUG]: $1${STOP}\n" #Debugging level logging; can be toggled via a switch
if [[ -f $LOG ]]; then debug () {
echo -e "$(date | awk '{print $4}') [DEBUG]: $1" >> $LOG printf "${BLUE}[DEBUG]: $1${STOP}\n"
fi if [[ -f $LOG ]]; then
} echo -e "$(date +"%T:%N") [DEBUG]: $1" >> $LOG
fi
}
#Otherwise, ignore debug calls;
else
debug () {
:
}
fi
#Information level logging; #Information level logging;
info () { info () {
printf "${CYAN}[INFO]:${STOP} $1\n" if [[ -z $2 ]]; then
if [[ -f $LOG ]]; then printf "${CYAN}[INFO]:${STOP} %s\n" "$1"
echo -e "$(date | awk '{print $4}') [INFO]: $1" >> $LOG if [[ -f $LOG ]]; then
echo -e "$(date +"%T:%N") [INFO]: $1" >> $LOG
fi
elif [[ -n $2 ]]; then
printf "${CYAN}[INFO]:${STOP} %s ${PURPLE}%s${STOP}\n" "$1" "$2"
if [[ -f $LOG ]]; then
printf "$(date +"%T:%N")${CYAN}[INFO]:${STOP} %s ${PURPLE}%s${STOP}\n" "$1" "$2" >> $LOG
fi
fi fi
} }
#Warning level logging; #Warning level logging;
warn () { warn () {
printf "${YELLOW}[WARNING]:${STOP} $1\n" printf "${YELLOW}[WARNING]:${STOP} $1\n"
if [[ -f $LOG ]]; then if [[ -f $LOG ]]; then
echo -e "$(date | awk '{print $4}') [WARN]: $1" >> $LOG echo -e "$(date +"%T:%N") [WARN]: $1" >> $LOG
fi fi
} }
#Error logging function; Errors are added to an array and a report file. #Error logging function; Errors are added to an array and a report file.
error () { error () {
echo $1 1>&2
# ` ^ Output error message to stderr
printf "${RED}[ERROR]: $1${STOP}\n" printf "${RED}[ERROR]: $1${STOP}\n"
# ^ Print it to the screen # ^ Print it to the screen
errors+=("$1") errors+=("$1")
# ^ And add to errors array # ^ And add to errors array
if [[ -f $LOG ]]; then if [[ -f $LOG ]]; then
echo -e "$(date | awk '{print $4}') [ERROR]: $1" >> $LOG echo -e "$(date +"%T:%N") [ERROR]: $1" >> $LOG
# ^ Log it with its' time and date # ^ Log it with its' time and date
fi fi
if [[ -f $REPORT ]]; then if [[ -f $REPORT ]]; then
@@ -118,7 +134,7 @@ error () {
ok () { ok () {
printf "${GREEN}[SUCCESS]: $1${STOP}\n" printf "${GREEN}[SUCCESS]: $1${STOP}\n"
if [[ -f $LOG ]]; then if [[ -f $LOG ]]; then
echo -e "$(date | awk '{print $4}') [SUCCESS]: $1" >> $LOG echo -e "$(date +"%T:%N") [SUCCESS]: $1" >> $LOG
fi fi
} }