Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 33 additions & 6 deletions run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,34 @@ reload_crond() {
watch_config() {
local file="$1"
if command -v inotifywait >/dev/null 2>&1; then
inotifywait -m -e close_write,move,delete "$file" |
while read -r _; do
generate_cron
reload_crond
local dir="$(dirname "$file")"
local base="$(basename "$file")"
inotifywait -m -e close_write,move,create,delete "$dir" --format '%e %f' |
while read -r events fname; do
[ "$fname" = "$base" ] || continue
if echo "$events" | grep -qE 'DELETE|MOVED_FROM'; then
echo "Warning: configuration file '$file' missing, skipping cron generation" >&2
elif [ -f "$file" ]; then
generate_cron
reload_crond
fi
done || true
else
local prev
prev="$(md5sum "$file" 2>/dev/null | awk '{print $1}' || true)"
if [ -f "$file" ]; then
prev="$(md5sum "$file" 2>/dev/null | awk '{print $1}' || true)"
else
prev="missing"
echo "Warning: configuration file '$file' missing, skipping cron generation" >&2
fi
while sleep 5; do
if [ ! -f "$file" ]; then
if [ "$prev" != "missing" ]; then
prev="missing"
echo "Warning: configuration file '$file' missing, skipping cron generation" >&2
fi
continue
fi
local curr
curr="$(md5sum "$file" 2>/dev/null | awk '{print $1}' || true)"
if [ "$curr" != "$prev" ]; then
Expand All @@ -35,7 +54,15 @@ watch_config() {
}

# Generate cron entries from environment/config
generate_cron
if [ -n "${CONFIG_FILE:-}" ]; then
if [ -f "$CONFIG_FILE" ]; then
generate_cron
else
echo "Warning: configuration file '$CONFIG_FILE' missing, skipping cron generation" >&2
fi
else
generate_cron
fi

crond -f -l 2 &
CROND_PID=$!
Expand Down
30 changes: 3 additions & 27 deletions test.sh
Original file line number Diff line number Diff line change
@@ -1,31 +1,7 @@
#!/usr/bin/env bash
set -euo pipefail

IMAGE_NAME=docker-cron-test
LOG_FILE=test.log
TEMP_CONFIG=config.json
bash tests/config_parser_test.sh
bash tests/watch_config_test.sh

cleanup() {
rm -f "$TEMP_CONFIG" "$LOG_FILE"
}
trap cleanup EXIT

# Build docker image
docker build -t "$IMAGE_NAME" .

# Create temporary config file
cat > "$TEMP_CONFIG" <<'CFG'
{
"jobs": [
{"cmd": "echo hello from cron", "interval": "* * * * *"}
]
}
CFG

# Run config parser inside container and display generated crontab
docker run --rm -v "$(pwd)/$TEMP_CONFIG:/config.json" -e CONFIG_FILE=/config.json --entrypoint /bin/sh "$IMAGE_NAME" -c '/app/config_parser.sh; cat /etc/crontabs/root' | tee "$LOG_FILE"

# Verify expected command is present in log
grep -q "echo hello from cron" "$LOG_FILE"

echo "Test completed successfully"
echo "All tests passed"
80 changes: 80 additions & 0 deletions tests/watch_config_test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#!/usr/bin/env bash
set -euo pipefail

# Ensure crond is available
if ! command -v crond >/dev/null 2>&1; then
if command -v apt-get >/dev/null 2>&1; then
apt-get update >/dev/null
apt-get install -y busybox >/dev/null
ln -sf /bin/busybox /usr/bin/crond
else
echo "crond not available, skipping watch_config test" >&2
exit 0
fi
fi

# Ensure config parser is accessible at /app
if [ ! -e /app ]; then
ln -s "$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)/app" /app
fi

# busybox crond expects /var/spool/cron/crontabs; map it to /etc/crontabs
if [ ! -e /var/spool/cron/crontabs ]; then
mkdir -p /var/spool/cron
mkdir -p /etc/crontabs
ln -s /etc/crontabs /var/spool/cron/crontabs
fi

TMPDIR=$(mktemp -d)
CONFIG="$TMPDIR/config.json"
LOG="$TMPDIR/run.log"
RUN_PID=0

cleanup() {
if [ "$RUN_PID" -ne 0 ]; then
pkill -P "$RUN_PID" >/dev/null 2>&1 || true
kill "$RUN_PID" >/dev/null 2>&1 || true
fi
rm -rf "$TMPDIR"
}
trap cleanup EXIT

cat >"$CONFIG" <<'CFG'
{
"jobs": [
{"cmd": "/bin/echo first", "interval": "* * * * *"}
]
}
CFG

CONFIG_FILE="$CONFIG" bash ./run.sh >"$LOG" 2>&1 &
RUN_PID=$!

# Allow initial generation
sleep 2

grep -q "echo first" /etc/crontabs/root

# Remove config file and ensure watcher keeps running
rm "$CONFIG"

sleep 7

kill -0 "$RUN_PID"

grep -q "configuration file.*missing" "$LOG"

# Recreate config file with different command
cat >"$CONFIG" <<'CFG'
{
"jobs": [
{"cmd": "/bin/echo second", "interval": "* * * * *"}
]
}
CFG

sleep 7

grep -q "echo second" /etc/crontabs/root

echo "watch_config test passed"
Loading