2022-07-25 02:29:58 +00:00
#!/bin/bash
2022-07-25 20:16:08 +00:00
2022-07-25 04:11:04 +00:00
commander( ) {
2022-07-25 04:03:57 +00:00
mapfile -t array < <( cli -m csv -c 'app chart_release query name,update_available,human_version,human_latest_version,container_images_update_available,status' | tr -d " \t\r" | grep -E " ,true( $|,) " | sort)
2022-07-31 19:03:45 +00:00
echo -e "🅄 🄿 🄳 🄰 🅃 🄴 🅂"
2022-07-31 19:16:40 +00:00
[ [ -z ${ array [*] } ] ] && echo "There are no updates available" && echo -e "\n" && return 0 || echo " Update(s) Available: ${# array [@] } "
2022-07-27 22:40:44 +00:00
echo " Asynchronous Updates: $update_limit "
2022-07-27 00:00:03 +00:00
[ [ -z $timeout ] ] && echo "Default Timeout: 500" && timeout = 500 || echo " Custom Timeout: $timeout "
2022-07-25 02:29:58 +00:00
[ [ " $timeout " -le 120 ] ] && echo "Warning: Your timeout is set low and may lead to premature rollbacks or skips"
2022-09-08 21:02:54 +00:00
[ [ $ignore_image_update = = "true" ] ] && echo "Image Updates: Disabled" || echo "Image Updates: Enabled"
2022-08-13 16:37:48 +00:00
pool = $( cli -c 'app kubernetes config' | grep -E "dataset\s\|" | awk -F '|' '{print $3}' | awk -F '/' '{print $1}' | tr -d " \t\n\r" )
2022-09-05 07:44:09 +00:00
index = 0
for app in " ${ array [@] } "
do
app_name = $( echo " $app " | awk -F ',' '{print $1}' ) #print out first catagory, name.
old_app_ver = $( echo " $app " | awk -F ',' '{print $4}' | awk -F '_' '{print $1}' | awk -F '.' '{print $1}' ) #previous/current Application MAJOR Version
new_app_ver = $( echo " $app " | awk -F ',' '{print $5}' | awk -F '_' '{print $1}' | awk -F '.' '{print $1}' ) #new Application MAJOR Version
old_chart_ver = $( echo " $app " | awk -F ',' '{print $4}' | awk -F '_' '{print $2}' | awk -F '.' '{print $1}' ) # Old Chart MAJOR version
new_chart_ver = $( echo " $app " | awk -F ',' '{print $5}' | awk -F '_' '{print $2}' | awk -F '.' '{print $1}' ) # New Chart MAJOR version
diff_app = $( diff <( echo " $old_app_ver " ) <( echo " $new_app_ver " ) ) #caluclating difference in major app versions
diff_chart = $( diff <( echo " $old_chart_ver " ) <( echo " $new_chart_ver " ) ) #caluclating difference in Chart versions
2022-09-15 01:06:04 +00:00
old_full_ver = $( echo " $app " | awk -F ',' '{print $4}' ) #Upgraded From
new_full_ver = $( echo " $app " | awk -F ',' '{print $5}' ) #Upraded To
2022-09-05 07:44:09 +00:00
#Skip application if its on ignore list
if printf '%s\0' " ${ ignore [@] } " | grep -iFxqz " ${ app_name } " ; then
echo -e " \n $app_name \nIgnored, skipping "
unset " array[ $index ] "
#Skip appliaction if major update and not ignoreing major versions
elif [ [ " $diff_app " != " $diff_chart " && $update_apps = = "true" ] ] ; then
echo -e " \n $app_name \nMajor Release, update manually "
unset " array[ $index ] "
2022-09-05 07:44:29 +00:00
# Skip update if application previously failed on this exact update version
elif grep -qs " ^ $app_name , " failed 2>/dev/null; then
failed_ver = $( grep " ^ $app_name , " failed | awk -F ',' '{print $2}' )
if [ [ " $failed_ver " = = " $new_full_ver " ] ] ; then
2022-09-08 21:02:54 +00:00
echo -e " \n $app_name \nSkipping previously failed version:\n $new_full_ver "
2022-09-07 02:15:27 +00:00
unset " array[ $index ] "
2022-09-05 07:44:29 +00:00
else
sed -i /" $app_name " ,/d failed
fi
2022-09-08 21:02:54 +00:00
#Skip Image updates if ignore image updates is set to true
elif [ [ $old_full_ver = = " $new_full_ver " && $ignore_image_update = = "true" ] ] ; then
echo -e " \n $app_name \nImage update, skipping.. "
unset " array[ $index ] "
2022-09-05 07:44:09 +00:00
fi
( ( index++) )
done
2022-09-05 18:38:01 +00:00
array = ( " ${ array [@] } " )
2022-09-05 18:43:01 +00:00
[ [ ${# array [@] } = = 0 ] ] && echo && echo && return
2022-09-05 07:44:09 +00:00
2022-09-05 08:46:41 +00:00
2022-09-05 18:43:01 +00:00
index = 0
2022-08-11 04:51:58 +00:00
while_count = 0
2022-08-13 23:03:32 +00:00
rm deploying 2>/dev/null
2022-08-21 23:54:10 +00:00
rm finished 2>/dev/null
2022-09-05 18:29:45 +00:00
while [ [ ${# processes [@] } != 0 || $( wc -l finished 2>/dev/null | awk '{ print $1 }' ) -lt " ${# array [@] } " ] ]
2022-07-25 20:42:57 +00:00
do
2022-08-24 22:39:08 +00:00
if while_status = $( cli -m csv -c 'app chart_release query name,update_available,human_version,human_latest_version,container_images_update_available,status' 2>/dev/null) ; then
2022-08-12 04:42:43 +00:00
( ( while_count++) )
2022-08-13 23:32:44 +00:00
[ [ -z $while_status ] ] && continue || echo -e " $while_count \n $while_status " > all_app_status
mapfile -t deploying_check < <( grep ",DEPLOYING," all_app_status)
2022-08-13 21:26:50 +00:00
for i in " ${ deploying_check [@] } "
2022-08-13 21:07:06 +00:00
do
app_name = $( echo " $i " | awk -F ',' '{print $1}' )
2022-08-13 21:26:50 +00:00
[ [ ! -e deploying ] ] && touch deploying
if ! grep -qs " $app_name ,DEPLOYING " deploying; then
echo " $app_name ,DEPLOYING " >> deploying
2022-08-13 21:07:06 +00:00
fi
done
2022-08-11 03:46:08 +00:00
else
echo "Middlewared timed out. Consider setting a lower number for async applications"
continue
2022-08-09 05:47:34 +00:00
fi
2022-07-26 05:44:09 +00:00
count = 0
2022-07-26 05:38:29 +00:00
for proc in " ${ processes [@] } "
do
2022-09-05 18:29:45 +00:00
kill -0 " $proc " & > /dev/null || unset " processes[ $count ] "
2022-07-27 21:07:53 +00:00
( ( count++) )
2022-07-26 05:38:29 +00:00
done
2022-09-05 18:29:45 +00:00
processes = ( " ${ processes [@] } " )
2022-09-05 18:43:01 +00:00
if [ [ $index -lt ${# array [@] } && " ${# processes [@] } " -lt " $update_limit " ] ] ; then
pre_process " ${ array [ $index ] } " &
2022-08-11 04:35:30 +00:00
processes += ( $! )
2022-09-05 18:43:01 +00:00
( ( index++) )
2022-09-04 23:40:29 +00:00
else
2022-08-13 21:41:50 +00:00
sleep 3
2022-07-25 20:42:57 +00:00
fi
done
2022-08-13 23:03:32 +00:00
rm deploying 2>/dev/null
2022-08-21 23:54:10 +00:00
rm finished 2>/dev/null
2022-07-31 19:03:45 +00:00
echo
echo
2022-07-25 04:11:04 +00:00
}
export -f commander
2022-07-25 04:03:57 +00:00
2022-07-27 01:04:27 +00:00
2022-08-12 16:33:54 +00:00
pre_process( ) {
2022-09-05 19:09:24 +00:00
app_name = $( echo " ${ array [ $index ] } " | awk -F ',' '{print $1}' ) #print out first catagory, name.
startstatus = $( echo " ${ array [ $index ] } " | awk -F ',' '{print $2}' ) #status of the app: STOPPED / DEPLOYING / ACTIVE
old_full_ver = $( echo " ${ array [ $index ] } " | awk -F ',' '{print $4}' ) #Upgraded From
new_full_ver = $( echo " ${ array [ $index ] } " | awk -F ',' '{print $5}' ) #Upraded To
rollback_version = $( echo " ${ array [ $index ] } " | awk -F ',' '{print $4}' | awk -F '_' '{print $2}' )
2022-08-26 04:39:26 +00:00
2022-08-13 16:37:48 +00:00
2022-08-26 04:39:26 +00:00
# Check if app is external services, append outcome to external_services file
2022-08-13 16:37:48 +00:00
[ [ ! -e external_services ] ] && touch external_services
if ! grep -qs " ^ $app_name , " external_services ; then
2022-08-24 11:09:59 +00:00
if ! grep -qs "/external-service" /mnt/" $pool " /ix-applications/releases/" $app_name " /charts/" $( find /mnt/" $pool " /ix-applications/releases/" $app_name " /charts/ -maxdepth 1 -type d -printf '%P\n' | sort -r | head -n 1) " /Chart.yaml; then
2022-08-13 16:37:48 +00:00
echo " $app_name ,false " >> external_services
else
echo " $app_name ,true " >> external_services
fi
fi
2022-09-04 23:23:22 +00:00
# If application is deploying prior to updating, attempt to wait for it to finish
if [ [ " $startstatus " = = "DEPLOYING" ] ] ; then
SECONDS = 0
while [ [ " $status " = = "DEPLOYING" ] ]
do
status = $( grep " ^ $app_name , " all_app_status | awk -F ',' '{print $2}' )
if [ [ " $SECONDS " -ge " $timeout " ] ] ; then
echo_array += ( "Application is stuck Deploying, Skipping to avoid damage" )
2022-09-04 23:27:58 +00:00
echo_array
2022-09-04 23:23:22 +00:00
return
fi
sleep 5
done
fi
2022-08-26 04:39:26 +00:00
# If user is using -S, stop app prior to updating
2022-08-12 16:44:32 +00:00
echo_array += ( " \n $app_name " )
2022-08-12 17:08:51 +00:00
if [ [ $stop_before_update = = "true" && " $startstatus " != "STOPPED" ] ] ; then # Check to see if user is using -S or not
[ [ " $verbose " = = "true" ] ] && echo_array += ( "Stopping prior to update.." )
if stop_app ; then
echo_array += ( "Stopped" )
else
echo_array += ( " Error: Failed to stop $app_name " )
echo_array
return 1
2022-07-25 02:29:58 +00:00
fi
2022-08-01 21:47:08 +00:00
fi
2022-08-26 04:39:26 +00:00
# Send app through update function
2022-08-12 12:53:35 +00:00
[ [ " $verbose " = = "true" ] ] && echo_array += ( "Updating.." )
2022-08-12 16:33:54 +00:00
if update_app ; then
2022-09-04 22:56:24 +00:00
if [ [ $old_full_ver = = " $new_full_ver " ] ] ; then
2022-09-04 22:58:20 +00:00
echo_array += ( "Updated Container Image" )
2022-09-04 22:56:24 +00:00
else
echo_array += ( " Updated\n $old_full_ver \n $new_full_ver " )
fi
2022-08-12 12:53:35 +00:00
else
2022-08-23 22:08:08 +00:00
echo_array += ( "Failed to update\nManual intervention may be required" )
2022-08-12 17:08:51 +00:00
echo_array
return
2022-08-12 12:53:35 +00:00
fi
2022-08-26 04:39:26 +00:00
# If app is external services, do not send for post processing
2022-08-13 16:49:47 +00:00
if grep -qs " ^ $app_name ,true " external_services ; then
echo_array
return
2022-09-04 22:56:24 +00:00
# If app is container image update, dont send for post processing
elif [ [ $old_full_ver = = " $new_full_ver " ] ] ; then
echo_array
return
2022-08-13 16:49:47 +00:00
else
2022-08-26 04:39:26 +00:00
post_process
2022-08-13 16:49:47 +00:00
fi
2022-07-25 22:50:44 +00:00
}
2022-08-12 16:33:54 +00:00
export -f pre_process
2022-07-25 02:29:58 +00:00
2022-08-26 04:39:26 +00:00
post_process( ) {
2022-07-25 02:29:58 +00:00
SECONDS = 0
count = 0
2022-08-04 22:48:55 +00:00
if [ [ $rollback = = "true" || " $startstatus " = = "STOPPED" ] ] ; then
2022-07-25 02:29:58 +00:00
while true
do
2022-08-31 03:36:34 +00:00
# If app reports ACTIVE right away, assume its a false positive and wait for it to change, or trust it after 5 updates to all_app_status
2022-08-13 23:32:44 +00:00
status = $( grep " ^ $app_name , " all_app_status | awk -F ',' '{print $2}' )
2022-08-24 21:51:19 +00:00
if [ [ $count -lt 1 && $status = = "ACTIVE" && " $( grep " ^ $app_name , " deploying 2>/dev/null | awk -F ',' '{print $2}' ) " != "DEPLOYING" ] ] ; then # If status shows up as Active or Stopped on the first check, verify that. Otherwise it may be a false report..
2022-08-12 13:33:13 +00:00
[ [ " $verbose " = = "true" ] ] && echo_array += ( " Verifying $status .. " )
2022-08-13 23:32:44 +00:00
before_loop = $( head -n 1 all_app_status)
2022-08-12 02:30:49 +00:00
current_loop = 0
2022-08-13 23:36:19 +00:00
until [ [ " $status " != "ACTIVE" || $current_loop -gt 4 ] ] # Wait for a specific change to app status, or 3 refreshes of the file to go by.
2022-08-11 05:27:11 +00:00
do
2022-08-14 23:43:07 +00:00
status = $( grep " ^ $app_name , " all_app_status | awk -F ',' '{print $2}' )
2022-08-11 05:37:53 +00:00
sleep 1
2022-08-13 23:32:44 +00:00
if ! echo -e " $( head -n 1 all_app_status) " | grep -qs ^" $before_loop " ; then
before_loop = $( head -n 1 all_app_status)
2022-08-11 06:18:53 +00:00
( ( current_loop++) )
fi
2022-08-11 05:27:11 +00:00
done
fi
( ( count++ ) )
2022-08-31 03:36:34 +00:00
2022-08-04 23:19:44 +00:00
if [ [ " $status " = = "ACTIVE" ] ] ; then
if [ [ " $startstatus " = = "STOPPED" ] ] ; then
[ [ " $verbose " = = "true" ] ] && echo_array += ( "Returing to STOPPED state.." )
2022-08-12 12:37:30 +00:00
if stop_app ; then
echo_array += ( "Stopped" )
else
echo_array += ( " Error: Failed to stop $app_name " )
2022-08-12 17:08:51 +00:00
echo_array
2022-08-12 12:37:30 +00:00
return 1
fi
2022-08-04 23:19:44 +00:00
break
else
echo_array += ( "Active" )
2022-08-12 13:33:13 +00:00
break
2022-08-04 23:19:44 +00:00
fi
2022-08-13 23:07:27 +00:00
elif [ [ " $SECONDS " -ge " $timeout " ] ] ; then
2022-08-04 22:48:55 +00:00
if [ [ $rollback = = "true" ] ] ; then
2022-09-05 07:44:09 +00:00
if [ [ " $failed " != "true" ] ] ; then
2022-09-07 02:23:20 +00:00
echo " $app_name , $new_full_ver " >> failed
2022-08-04 23:19:44 +00:00
echo_array += ( " Error: Run Time( $SECONDS ) for $app_name has exceeded Timeout( $timeout ) " )
echo_array += ( "If this is a slow starting application, set a higher timeout with -t" )
echo_array += ( "If this applicaion is always DEPLOYING, you can disable all probes under the Healthcheck Probes Liveness section in the edit configuration" )
2022-09-07 02:23:20 +00:00
echo_array += ( "Reverting update.." )
2022-08-24 21:51:19 +00:00
if rollback_app ; then
echo_array += ( "Rolled Back" )
else
echo_array += ( " Error: Failed to rollback $app_name \nAbandoning " )
echo_array
return 1
fi
failed = "true"
SECONDS = 0
count = 0
2022-08-26 04:39:26 +00:00
continue #run back post_process function if the app was stopped prior to update
2022-08-04 23:19:44 +00:00
else
echo_array += ( " Error: Run Time( $SECONDS ) for $app_name has exceeded Timeout( $timeout ) " )
echo_array += ( "The application failed to be ACTIVE even after a rollback" )
2022-08-21 22:44:22 +00:00
echo_array += ( "Manual intervention is required\nStopping, then Abandoning" )
if stop_app ; then
echo_array += ( "Stopped" )
else
echo_array += ( " Error: Failed to stop $app_name " )
echo_array
return 1
fi
2022-08-04 22:48:55 +00:00
break
fi
else
2022-09-07 02:23:20 +00:00
echo " $app_name , $new_full_ver " >> failed
2022-08-04 23:19:44 +00:00
echo_array += ( " Error: Run Time( $SECONDS ) for $app_name has exceeded Timeout( $timeout ) " )
echo_array += ( "If this is a slow starting application, set a higher timeout with -t" )
echo_array += ( "If this applicaion is always DEPLOYING, you can disable all probes under the Healthcheck Probes Liveness section in the edit configuration" )
2022-08-21 22:44:22 +00:00
echo_array += ( "Manual intervention is required\nStopping, then Abandoning" )
if stop_app ; then
echo_array += ( "Stopped" )
else
echo_array += ( " Error: Failed to stop $app_name " )
echo_array
return 1
fi
2022-08-21 22:45:53 +00:00
break
2022-08-04 22:48:55 +00:00
fi
2022-07-25 02:29:58 +00:00
else
2022-07-25 23:11:56 +00:00
[ [ " $verbose " = = "true" ] ] && echo_array += ( " Waiting $(( timeout-SECONDS)) more seconds for $app_name to be ACTIVE " )
2022-08-12 03:20:04 +00:00
sleep 5
2022-07-25 02:29:58 +00:00
continue
fi
done
fi
2022-08-12 17:08:51 +00:00
echo_array
}
2022-08-26 04:39:26 +00:00
export -f post_process
2022-07-25 23:21:41 +00:00
2022-08-04 22:48:55 +00:00
2022-08-24 21:51:19 +00:00
rollback_app( ) {
count = 0
2022-08-24 22:39:08 +00:00
app_update_avail = $( grep " ^ $app_name , " all_app_status | awk -F ',' '{print $3}' )
while [ [ $app_update_avail = = "false" ] ]
2022-08-24 21:51:19 +00:00
do
2022-08-24 22:39:08 +00:00
app_update_avail = $( grep " ^ $app_name , " all_app_status | awk -F ',' '{print $3}' )
2022-08-24 21:51:19 +00:00
if [ [ $count -gt 2 ] ] ; then # If failed to rollback app 3 times, return failure to parent shell
return 1
elif ! cli -c " app chart_release rollback release_name=\" $app_name \" rollback_options={\"item_version\": \" $rollback_version \"} " & > /dev/null ; then
before_loop = $( head -n 1 all_app_status)
( ( count++) )
until [ [ $( head -n 1 all_app_status) != " $before_loop " ] ] # Upon failure, wait for status update before continuing
do
sleep 1
done
else
break
fi
done
}
2022-08-26 04:39:26 +00:00
update_app( ) {
current_loop = 0
while true
do
update_avail = $( grep " ^ $app_name , " all_app_status | awk -F ',' '{print $3","$6}' )
if [ [ $update_avail = ~ "true" ] ] ; then
if ! cli -c 'app chart_release upgrade release_name=' '"' " $app_name " '"' & > /dev/null ; then
before_loop = $( head -n 1 all_app_status)
current_loop = 0
until [ [ " $( grep " ^ $app_name , " all_app_status | awk -F ',' '{print $3","$6}' ) " != " $update_avail " ] ] # Wait for a specific change to app status, or 3 refreshes of the file to go by.
do
if [ [ $current_loop -gt 2 ] ] ; then
cli -c 'app chart_release upgrade release_name=' '"' " $app_name " '"' & > /dev/null || return 1 # After waiting, attempt an update once more, if fails, return error code
elif ! echo -e " $( head -n 1 all_app_status) " | grep -qs ^" $before_loop " ; then # The file has been updated, but nothing changed specifically for the app.
before_loop = $( head -n 1 all_app_status)
( ( current_loop++) )
fi
sleep 1
done
fi
break
elif [ [ ! $update_avail = ~ "true" ] ] ; then
break
else
sleep 3
fi
done
}
export -f update_app
stop_app( ) {
count = 0
while [ [ " $status " != "STOPPED" ] ]
do
status = $( grep " ^ $app_name , " all_app_status | awk -F ',' '{print $2}' )
if [ [ $count -gt 2 ] ] ; then # If failed to stop app 3 times, return failure to parent shell
return 1
elif ! cli -c 'app chart_release scale release_name=' \" " $app_name " \" \ 'scale_options={"replica_count": 0}' & > /dev/null ; then
before_loop = $( head -n 1 all_app_status)
( ( count++) )
until [ [ $( head -n 1 all_app_status) != " $before_loop " ] ] # Upon failure, wait for status update before continuing
do
sleep 1
done
else
break
fi
done
}
export -f stop_app
2022-08-12 17:08:51 +00:00
echo_array( ) {
2022-07-25 23:38:10 +00:00
#Dump the echo_array, ensures all output is in a neat order.
2022-07-25 23:21:41 +00:00
for i in " ${ echo_array [@] } "
do
echo -e " $i "
done
2022-08-24 22:39:08 +00:00
final_check
2022-07-25 02:29:58 +00:00
}
2022-08-12 17:08:51 +00:00
export -f echo_array
2022-08-21 23:54:10 +00:00
2022-08-24 22:39:08 +00:00
2022-08-21 23:54:10 +00:00
final_check( ) {
[ [ ! -e finished ] ] && touch finished
echo " $app_name ,finished " >> finished
2022-08-26 04:39:26 +00:00
}