Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test jobs before adding them to the crontab file #6

Merged
merged 10 commits into from
Oct 26, 2024
6 changes: 5 additions & 1 deletion functions.sh
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
timestamp() {
date -u "+%Y-%m-%d %H:%M:%S %Z"
}

isTrue() {
case $1 in
"True" | "TRUE" | "true" | 1)
Expand All @@ -11,6 +15,6 @@ isTrue() {

log() {
if isTrue "$DEBUG"; then
echo "$(timestamp)" "$@"
echo "$(timestamp) |" "$@"
fi
}
3 changes: 2 additions & 1 deletion startup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
DIR=$(dirname "$0")
. "$DIR/functions.sh"

touch /root/crontab
# Create empty crontab file
true > /root/crontab

if isTrue "$DEBUG"; then
supercronic -debug -inotify /root/crontab &
Expand Down
66 changes: 45 additions & 21 deletions update_cron.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,13 @@ DIR=$(dirname "$0")
. "$DIR/functions.sh"

# Temp cron file paths
CRON_FILE_TEST="/tmp/cron_test"
CRON_FILE_NEW="/root/crontab.new"
CRON_FILE="/root/crontab"
CRON_LOG_DIR=${CRON_LOG_DIR:-/var/log/cron}

mkdir -p "$CRON_LOG_DIR"

timestamp() {
date -u "+%Y-%m-%d %H:%M:%S %Z"
}

# Function to extract specific cron job labels from a container
extract_cron_jobs() {
_container_id=$1
Expand All @@ -34,23 +31,24 @@ extract_cron_command() {

# Get the project name
if [ -z "$COMPOSE_PROJECT_NAME" ]; then
echo "$(timestamp) COMPOSE_PROJECT_NAME is not set. The service cron will run tasks for all Docker containers."
echo "$(timestamp) | The COMPOSE_PROJECT_NAME variable isn't set. The cron service handles jobs for all docker containers (all docker-compose stacks) on the server."
containers=$(docker ps -q)
else
echo "$(timestamp) The service cron will run tasks for Docker containers defined in the COMPOSE_PROJECT_NAME: $COMPOSE_PROJECT_NAME"
echo "$(timestamp) | The cron service handles jobs for the docker-compose stack defined in the COMPOSE_PROJECT_NAME variable: $COMPOSE_PROJECT_NAME"
containers=$(docker ps --filter "label=com.docker.compose.project=$COMPOSE_PROJECT_NAME" -q)
fi

echo "$(timestamp) Updating cron jobs..."
echo "$(timestamp) | Updating cron jobs..."
touch $CRON_FILE_NEW

# Process each container
for container in $containers; do
cron_jobs=$(extract_cron_jobs "$container")
target_container=$(docker inspect -f '{{.Name}}' "$container" | cut -c2-) # Remove leading /
if [ -z "$cron_jobs" ]; then
log "No cron jobs found for container: $container"
log "No cron jobs found for container: $target_container ($container)"
else
log "Processing container: $container"
log "Processing container: $target_container ($container)"

echo "$cron_jobs" | while IFS= read -r job; do
decoded_job=$(decode_cron_job "$job")
Expand All @@ -64,12 +62,22 @@ for container in $containers; do

# Check if both schedule and command labels are set
if [ -n "$job_schedule" ] && [ -n "$job_command" ]; then
target_container=$(docker inspect -f '{{.Name}}' "$container" | cut -c2-) # Remove leading /
cron_entry="$job_schedule docker exec $target_container sh -c '$job_command' 2>&1 | tee -a $CRON_LOG_DIR/\$(date -u +\%Y-\%m-\%d_\%H-\%M-\%S_\%Z)_$job_key.log"
echo "$cron_entry" >> $CRON_FILE_NEW # Write in one line to the cron file
log "Scheduled task for $target_container: $cron_entry"
# Run the supercronic test
echo "$cron_entry" > $CRON_FILE_TEST
if ! supercronic -test $CRON_FILE_TEST > /dev/null 2>&1; then
echo "$(timestamp) | ========================================================"
printf "\nERROR ERROR ERROR ERROR ERROR ERROR ERROR ERROR ERROR ERROR ERROR ERROR ERROR ERROR ERROR ERROR ERROR\n\n"
echo "BAD CRON JOB: '$cron_entry'"
supercronic -debug -test $CRON_FILE_TEST
printf "==================================================================================\n\n"
# TODO make the cron container unhealthy
else
echo "$cron_entry" >> $CRON_FILE_NEW # Write in one line to the cron file
log "Scheduled task for $target_container: $cron_entry"
fi
else
echo "$(timestamp) Error: job_schedule or job_command is missing."
echo "$(timestamp) | Error: job_schedule or job_command is missing."
fi
done
fi
Expand All @@ -78,18 +86,34 @@ done
# Check if there are changes
if ! diff -u "$CRON_FILE" "$CRON_FILE_NEW" > /dev/null; then
# Print the changes in the crontab:
printf "\n\n%s Changes in the crontab file:\n" "$(timestamp)"
printf "\n%s | Changes in the crontab file:\n" "$(timestamp)"
diff -u "$CRON_FILE" "$CRON_FILE_NEW" | tail -n +3 # Remove the first two lines containing file names

# Print the updated crontab file
printf "\n%s Updated crontab file:\n=========================================\n" "$(timestamp)"
cat "$CRON_FILE_NEW"
printf "=========================================\n\n"
if [ ! -s "$CRON_FILE_NEW" ]; then
printf "\n%s | NO JOBS IN CRONTAB FILE\n\n" "$(timestamp)"
else
# Print the updated crontab file
printf "\n%s | Updated crontab file:\n=========================================\n" "$(timestamp)"
cat "$CRON_FILE_NEW"
printf "=========================================\n\n"
fi

# Update the crontab file
cat "$CRON_FILE_NEW" > "$CRON_FILE"
# Update the crontab file if it looks good for supercronic (we tested it one by one line above, but to make sure)
if ! supercronic -test $CRON_FILE_NEW > /dev/null 2>&1; then
echo "$(timestamp) | ########################################################"
printf "\nERROR ERROR ERROR ERROR ERROR ERROR ERROR ERROR ERROR ERROR ERROR ERROR ERROR ERROR ERROR ERROR ERROR\n\n"
echo "SOMETHING IS WRONG IN THE CRONTAB FILE"
supercronic -debug -test $CRON_FILE_NEW
echo "ERROR: CHANGES ARE NOT APPLIED."
echo "CURRENT CRONTAB FILE IS:"
cat "$CRON_FILE"
printf "##################################################################################\n\n"
# TODO make the cron container unhealthy
else
cat "$CRON_FILE_NEW" > "$CRON_FILE"
fi
else
echo "$(timestamp) No changes detected in crontab file."
echo "$(timestamp) | No changes detected in crontab file."
fi

rm "$CRON_FILE_NEW"
Loading