docker-crontab/docker-entrypoint

271 lines
8.5 KiB
Plaintext
Raw Normal View History

2017-02-12 16:28:53 -07:00
#!/usr/bin/env bash
set -e
2022-07-16 08:33:41 -07:00
DOCKER_SOCK=/var/run/docker.sock
CRONTAB_FILE=/etc/crontabs/docker
# For local testing only.
#HOME_DIR=.
2022-07-16 08:38:01 -07:00
if [ -z "${HOME_DIR}" ]; then
echo "HOME_DIR not set."
exit 1
fi
2022-07-16 08:33:41 -07:00
# Ensure dir exist - in case of volume mapping.
mkdir -p "${HOME_DIR}"/jobs "${HOME_DIR}"/projects
2022-07-16 08:43:14 -07:00
if [ -z "${DOCKER_HOST}" ] && [ -a "${DOCKER_PORT_2375_TCP}" ]; then
2017-02-15 10:58:57 -07:00
export DOCKER_HOST='tcp://docker:2375'
fi
2017-02-12 16:28:53 -07:00
if [ "${LOG_FILE}" == "" ]; then
LOG_DIR=/var/log/crontab
LOG_FILE=${LOG_DIR}/jobs.log
mkdir -p ${LOG_DIR}
touch ${LOG_FILE}
fi
normalize_config() {
2022-07-16 08:28:20 -07:00
JSON_CONFIG={}
if [ -f "${HOME_DIR}/config.json" ]; then
2022-07-16 08:28:20 -07:00
JSON_CONFIG="$(cat "${HOME_DIR}"/config.json)"
elif [ -f "${HOME_DIR}/config.toml" ]; then
2022-07-16 08:28:20 -07:00
JSON_CONFIG="$(rq -t <<< "$(cat "${HOME_DIR}"/config.toml)")"
elif [ -f "${HOME_DIR}/config.yml" ]; then
2022-07-16 08:28:20 -07:00
JSON_CONFIG="$(rq -y <<< "$(cat "${HOME_DIR}"/config.yml)")"
elif [ -f "${HOME_DIR}/config.yaml" ]; then
2022-07-16 08:28:20 -07:00
JSON_CONFIG="$(rq -y <<< "$(cat "${HOME_DIR}"/config.yaml)")"
fi
2022-07-16 08:28:20 -07:00
jq 'map(.)' "${JSON_CONFIG}" > "${HOME_DIR}"/config.working.json
}
ensure_docker_socket_accessible() {
if ! grep -q "^docker:" /etc/group; then
# Ensure 'docker' user has permissions for docker socket (without changing permissions).
DOCKER_GID=$(stat -c '%g' ${DOCKER_SOCK})
if [ "${DOCKER_GID}" != "0" ]; then
if ! grep -qE "^[^:]+:[^:]+:${DOCKER_GID}:" /etc/group; then
# No group with such gid exists - create group docker.
2022-07-16 08:13:11 -07:00
addgroup -g "${DOCKER_GID}" docker
adduser docker docker
else
# Group with such gid exists - add user "docker" to this group.
2022-07-16 08:15:18 -07:00
DOCKER_GROUP_NAME=$(getent group "${DOCKER_GID}" | awk -F':' '{{ print $1 }}')
2022-07-16 08:43:14 -07:00
adduser docker "${DOCKER_GROUP_NAME}"
fi
else
# Docker socket belongs to "root" group - add user "docker" to this group.
adduser docker root
fi
fi
}
2017-11-14 13:54:20 -07:00
slugify() {
2022-07-16 08:43:14 -07:00
echo "${@}" | iconv -t ascii | sed -r s/[~^]+//g | sed -r s/[^a-zA-Z0-9]+/-/g | sed -r s/^-+\|-+$//g | tr '[:upper:]' '[:lower:]'
2017-11-14 13:54:20 -07:00
}
2017-02-12 16:28:53 -07:00
make_image_cmd() {
2022-07-16 08:13:11 -07:00
DOCKERARGS=$(echo "${1}" | jq -r .dockerargs)
VOLUMES=$(echo "${1}" | jq -r '.volumes | map(" -v " + .) | join("")')
PORTS=$(echo "${1}" | jq -r '.ports | map(" -p " + .) | join("")')
EXPOSE=$(echo "${1}" | jq -r '.expose | map(" --expose " + .) | join("")')
NAME=$(echo "${1}" | jq -r 'select(.name != null) | .name')
NETWORK=$(echo "${1}" | jq -r 'select(.network != null) | .network')
ENVIRONMENT=$(echo "${1}" | jq -r '.environment | map(" -e " + .) | join("")')
2017-02-12 16:28:53 -07:00
if [ "${DOCKERARGS}" == "null" ]; then DOCKERARGS=; fi
2022-07-16 08:16:22 -07:00
if [ -n "${NAME}" ]; then DOCKERARGS="${DOCKERARGS} --rm --name ${NAME} "; fi
if [ -n "${NETWORK}" ]; then DOCKERARGS="${DOCKERARGS} --network ${NETWORK} "; fi
if [ -n "${VOLUMES}" ]; then DOCKERARGS="${DOCKERARGS}${VOLUMES}"; fi
if [ -n "${ENVIRONMENT}" ]; then DOCKERARGS="${DOCKERARGS}${ENVIRONMENT}"; fi
if [ -n "${PORTS}" ]; then DOCKERARGS="${DOCKERARGS}${PORTS}"; fi
if [ -n "${EXPOSE}" ]; then DOCKERARGS="${DOCKERARGS}${EXPOSE}"; fi
2022-07-16 08:13:11 -07:00
IMAGE=$(echo "${1}" | jq -r .image | envsubst)
TMP_COMMAND=$(echo "${1}" | jq -r .command)
2017-02-12 16:28:53 -07:00
echo "docker run ${DOCKERARGS} ${IMAGE} ${TMP_COMMAND}"
}
make_container_cmd() {
2022-07-16 08:13:11 -07:00
DOCKERARGS=$(echo "${1}" | jq -r .dockerargs)
2017-02-12 16:28:53 -07:00
if [ "${DOCKERARGS}" == "null" ]; then DOCKERARGS=; fi
2022-07-16 08:13:11 -07:00
SCRIPT_NAME=$(echo "${1}" | jq -r .name)
2022-07-16 08:43:14 -07:00
SCRIPT_NAME=$(slugify "${SCRIPT_NAME}")
2022-07-16 08:13:11 -07:00
PROJECT=$(echo "${1}" | jq -r .project)
CONTAINER=$(echo "${1}" | jq -r .container | envsubst)
TMP_COMMAND=$(echo "${1}" | jq -r .command)
2017-02-12 16:28:53 -07:00
if [ "${PROJECT}" != "null" ]; then
# Create bash script to detect all running containers.
2017-06-17 20:10:47 -06:00
if [ "${SCRIPT_NAME}" == "null" ]; then
SCRIPT_NAME=$(cat /proc/sys/kernel/random/uuid)
fi
2022-07-16 08:13:11 -07:00
cat << EOF > "${HOME_DIR}"/projects/"${SCRIPT_NAME}".sh
2017-02-12 21:37:00 -07:00
#!/usr/bin/env bash
2017-02-12 16:28:53 -07:00
set -e
2017-06-17 20:10:47 -06:00
CONTAINERS=\$(docker ps --format '{{.Names}}' | grep -E "^${PROJECT}_${CONTAINER}.[0-9]+")
2017-02-12 16:28:53 -07:00
for CONTAINER_NAME in \$CONTAINERS; do
2017-02-14 07:18:25 -07:00
docker exec ${DOCKERARGS} \${CONTAINER_NAME} ${TMP_COMMAND}
2017-02-12 16:28:53 -07:00
done
EOF
2017-06-17 20:10:47 -06:00
echo "/bin/bash ${HOME_DIR}/projects/${SCRIPT_NAME}.sh"
2017-02-12 16:28:53 -07:00
else
echo "docker exec ${DOCKERARGS} ${CONTAINER} ${TMP_COMMAND}"
fi
}
2017-02-14 07:44:14 -07:00
#make_host_cmd() {
# HOST_BINARY=$(echo ${1} | jq -r .host)
# TMP_COMMAND=$(echo ${1} | jq -r .command)
# echo "${HOST_BINARY} ${TMP_COMMAND}"
#}
2017-02-12 16:28:53 -07:00
make_cmd() {
2022-07-16 08:13:11 -07:00
if [ "$(echo "${1}" | jq -r .image)" != "null" ]; then
2022-07-16 08:43:14 -07:00
make_image_cmd "${1}"
2022-07-16 08:13:11 -07:00
elif [ "$(echo "${1}" | jq -r .container)" != "null" ]; then
2022-07-16 08:43:14 -07:00
make_container_cmd "${1}"
2017-02-14 07:44:14 -07:00
#elif [ "$(echo ${1} | jq -r .host)" != "null" ]; then
2022-07-16 08:43:14 -07:00
# make_host_cmd "${1}"
2017-02-12 16:28:53 -07:00
else
2022-07-16 08:13:11 -07:00
echo "${1}" | jq -r .command
2017-02-12 16:28:53 -07:00
fi
}
parse_schedule() {
case $1 in
"@yearly")
echo "0 0 1 1 *"
2017-02-12 16:28:53 -07:00
;;
"@annually")
echo "0 0 1 1 *"
2017-02-12 16:28:53 -07:00
;;
"@monthly")
echo "0 0 1 * *"
2017-02-12 16:28:53 -07:00
;;
"@weekly")
echo "0 0 * * 0"
2017-02-12 16:28:53 -07:00
;;
"@daily")
echo "0 0 * * *"
2017-02-12 16:28:53 -07:00
;;
"@midnight")
echo "0 0 * * *"
2017-02-12 16:28:53 -07:00
;;
"@hourly")
echo "0 * * * *"
2017-02-12 16:28:53 -07:00
;;
"@every")
TIME=$2
TOTAL=0
2022-07-16 08:43:14 -07:00
M=$(echo "${TIME}" | grep -o '[0-9]\+m')
H=$(echo "${TIME}" | grep -o '[0-9]\+h')
D=$(echo "${TIME}" | grep -o '[0-9]\+d')
2017-02-12 16:28:53 -07:00
if [ -n "${M}" ]; then
2022-07-16 08:14:30 -07:00
TOTAL=$((TOTAL + ${M::-1}))
2017-02-12 16:28:53 -07:00
fi
if [ -n "${H}" ]; then
2022-07-16 08:14:30 -07:00
TOTAL=$((TOTAL + ${H::-1} * 60))
2017-02-12 16:28:53 -07:00
fi
if [ -n "${D}" ]; then
2022-07-16 08:14:30 -07:00
TOTAL=$((TOTAL + ${D::-1} * 60 * 24))
2017-02-12 16:28:53 -07:00
fi
echo "*/${TOTAL} * * * *"
2017-02-12 16:28:53 -07:00
;;
*)
echo "${@}"
;;
esac
}
function build_crontab() {
rm -rf ${CRONTAB_FILE}
2017-02-14 07:18:25 -07:00
ONSTART=()
2022-07-16 08:17:17 -07:00
while read -r i ; do
2017-02-12 16:28:53 -07:00
2022-07-16 08:13:11 -07:00
SCHEDULE=$(jq -r .["$i"].schedule "${CONFIG}" | sed 's/\*/\\*/g')
2017-02-12 16:28:53 -07:00
if [ "${SCHEDULE}" == "null" ]; then
2022-07-16 08:13:11 -07:00
echo "Schedule Missing: $(jq -r .["$i"].schedule "${CONFIG}")"
2017-02-12 16:28:53 -07:00
continue
fi
2022-07-16 08:13:11 -07:00
SCHEDULE=$(parse_schedule "${SCHEDULE}" | sed 's/\\//g')
2017-02-12 16:28:53 -07:00
2022-07-16 08:51:38 -07:00
COMMAND=$(jq -r .["$i"].command "${CONFIG}")
if [ "${COMMAND}" == "null" ]; then
echo "Command Missing: '${COMMAND}'"
2017-02-12 16:28:53 -07:00
continue
fi
2022-07-16 08:13:11 -07:00
COMMENT=$(jq -r .["$i"].comment "${CONFIG}")
2017-02-15 13:42:35 -07:00
if [ "${COMMENT}" != "null" ]; then
echo "# ${COMMENT}" >> ${CRONTAB_FILE}
fi
2022-07-16 08:13:11 -07:00
SCRIPT_NAME=$(jq -r .["$i"].name "${CONFIG}")
2022-07-16 08:43:14 -07:00
SCRIPT_NAME=$(slugify "${SCRIPT_NAME}")
if [ "${SCRIPT_NAME}" == "null" ]; then
SCRIPT_NAME=$(cat /proc/sys/kernel/random/uuid)
fi
2017-02-15 11:16:11 -07:00
COMMAND="/bin/bash ${HOME_DIR}/jobs/${SCRIPT_NAME}.sh"
2022-07-16 08:13:11 -07:00
cat << EOF > "${HOME_DIR}"/jobs/"${SCRIPT_NAME}".sh
2017-02-15 11:16:11 -07:00
#!/usr/bin/env bash
set -e
2017-06-17 20:55:56 -06:00
echo "Start Cronjob **${SCRIPT_NAME}** ${COMMENT}"
2017-02-15 11:16:11 -07:00
2022-07-16 08:13:11 -07:00
$(make_cmd "$(jq -c .["$i"] "${CONFIG}")")
2017-02-15 11:16:11 -07:00
EOF
2022-07-16 08:51:38 -07:00
TRIGGER=$(jq -r .["$i"].trigger "${CONFIG}")
if [ "${TRIGGER}" != "null" ]; then
2022-07-16 08:17:17 -07:00
while read -r j ; do
2022-07-16 08:51:38 -07:00
TRIGGER_COMMAND=$(jq .["$i"].trigger["$j"].command "${CONFIG}")
if [ "${TRIGGER_COMMAND}" == "null" ]; then
echo "Command Missing: '${TRIGGER_COMMAND}'"
2017-02-12 16:28:53 -07:00
continue
fi
make_cmd "${TRIGGER_COMMAND}" >> "${HOME_DIR}"/jobs/"${SCRIPT_NAME}".sh
2022-07-16 08:13:11 -07:00
done < <(jq -r '.['"$i"'].trigger|keys[]' "${CONFIG}")
2017-02-12 16:28:53 -07:00
fi
2022-07-16 08:13:11 -07:00
echo "echo \"End Cronjob **${SCRIPT_NAME}** ${COMMENT}\"" >> "${HOME_DIR}"/jobs/"${SCRIPT_NAME}".sh
2017-06-17 20:55:56 -06:00
2017-02-12 16:28:53 -07:00
echo "${SCHEDULE} ${COMMAND}" >> ${CRONTAB_FILE}
2017-02-14 07:18:25 -07:00
2022-07-16 08:13:11 -07:00
if [ "$(jq -r .["$i"].onstart "${CONFIG}")" == "true" ]; then
2017-02-14 07:18:25 -07:00
ONSTART+=("${COMMAND}")
fi
2022-07-16 08:13:11 -07:00
done < <(jq -r '.|keys[]' "${CONFIG}")
2017-02-12 16:28:53 -07:00
2017-02-15 07:03:07 -07:00
echo "##### crontab generation complete #####"
2017-02-12 16:28:53 -07:00
cat ${CRONTAB_FILE}
2017-02-14 07:18:25 -07:00
2017-02-15 07:03:07 -07:00
echo "##### run commands with onstart #####"
for COMMAND in "${ONSTART[@]}"; do
2017-02-15 07:03:07 -07:00
echo "${COMMAND}"
2017-02-14 07:44:14 -07:00
${COMMAND} &
2017-02-14 07:18:25 -07:00
done
2017-02-12 16:28:53 -07:00
}
start_app() {
normalize_config
2022-07-16 08:28:20 -07:00
export CONFIG=${HOME_DIR}/config.working.json
if [ ! -f "${CONFIG}" ]; then
echo "Unable to find ${CONFIG}."
exit 1
2017-02-12 16:57:19 -07:00
fi
2022-07-16 08:43:14 -07:00
if [ "${1}" == "crond" ]; then
2022-07-16 08:28:20 -07:00
build_crontab
fi
2022-07-16 08:43:14 -07:00
echo "${@}"
exec "${@}"
}
2017-02-12 16:28:53 -07:00
2022-07-16 08:33:41 -07:00
ensure_docker_socket_accessible
2022-07-16 08:43:14 -07:00
start_app "${@}"