blob: 05445963e743e058d03432d5a93811deabec62f9 (
plain) (
tree)
|
|
#!/bin/bash -a
# cychedelic DMT daemon
# cychedelic is an automated Continuous Deployment solution. See the README for
# more information.
CYCHE_SERVICE_DIR="/data/services"
CYCHE_LOG_DIR="/data/logs"
CYCHE_STATUS_FILE="/data/status"
CYCHE_VERSION_FILE="/version"
source config.sh
sane_path_info() {
# Permit only '-_./' and alphanumeric, as in "/Foo/bar_baz/ex-420.txt".
# Fail if any ".." or "//" is detected to prevent bad file access.
# Final path info is split on '/' for easy forming into an array.
( (! echo "$PATH_INFO" | grep -Eq '^[-_\.\/A-Za-z0-9]+$') \
|| (! echo "$PATH_INFO" | grep -Evq '\.\.|//') ) \
&& exit 1
echo "$PATH_INFO" | sed 's/\// /g'
}
integer() {
[ "$1" -eq "$1" ] >/dev/null 2>&1
}
escape_html() {
sed 's/&/\&/g; s/</\</g; s/>/\>/g; s/"/\"/g; s/'"'"'/\'/g'
}
escape_json() {
sed 's/\\/\\\\/g; s/\r/\\r/g; s/\t/\\t/g; s/"/\\"/g' \
| awk '{printf "%s\\n", $0}'
}
template() {
[ -n "$2" ] && printf 'Content-type: %s\n\n' "$2"
template.awk "$1" | bash
}
newest_job() {
ls -A "$CYCHE_LOG_DIR" | sort -rn | head -n1
}
oldest_job() {
ls -A "$CYCHE_LOG_DIR" | sort -n | head -n1
}
log_tail() {
tail -n "$CYCHE_LOG_TAIL_LENGTH" "$CYCHE_LOG_DIR/$1/log" | sed 's/\r//g'
}
api_status() {
status=$(cat "$CYCHE_STATUS_FILE")
[ "$status" == "" ] && active="false" || active="true"
integer "$status" && job="$status" || job="-1"
printf 'Content-type: text/json\n\n{'
printf '"version":"%s",' "$(cat "$CYCHE_VERSION_FILE")"
printf '"active":%s,' "$active"
printf '"job":%i,' "$job"
printf '"newest":%i,' "$(newest_job)"
printf '"oldest":%i}' "$(oldest_job)"
}
api_job() {
[ -z "$1" ] && job="$(newest_job)" || job="$1"
jobdir="$CYCHE_LOG_DIR/$job"
if [ -d "$jobdir" ]; then
status=$(cat "$CYCHE_STATUS_FILE")
result=$( ([ "$status" == "$job" ] && echo "active") \
|| ([ -f "$jobdir/fail" ] && echo "fail") \
|| echo "pass" )
printf 'Content-type: text/json\n\n{'
printf '"job":%i,' "$job"
printf '"hash":"%s",' "$(cat "$jobdir/hash")"
printf '"reason":"%s",' "$(cat "$jobdir/reason")"
printf '"service":"%s",' "$(cat "$jobdir/service")"
printf '"time":%i,' "$(cat "$jobdir/time")"
printf '"result":"%s",' "$result"
printf '"log":"%s"}' "$(log_tail "$job" | escape_json)"
fi
}
api_log() {
[ -z "$1" ] && job="$(newest_job)" || job="$1"
jobdir="$CYCHE_LOG_DIR/$job"
if [ -d "$jobdir" ]; then
printf 'Content-type: text/plain\n\n'
cat "$jobdir/log"
fi
}
route=($(sane_path_info)) || exit 1
case ${route[0]} in
"api")
case ${route[1]} in
"status") api_status ;;
"job") api_job "${route[2]}" ;;
"log") api_log "${route[2]}" ;;
esac
;;
"")
page_template="html/jobs.html"
template "html/master.html" text/html
;;
"services")
page_template="html/services.html"
template "html/master.html" text/html
;;
"stats")
page_template="html/stats.html"
template "html/master.html" text/html
;;
"style.css")
template "style.css" text/css
;;
"script.js")
template "script.js" text/javascript
;;
"favicon.png")
printf 'Content-type: image/png\n\n'
cat "favicon.png"
;;
esac
|