11#! /usr/bin/env bash
22set -e
33
4- if [ -z " $DOCKER_HOST " -a " $DOCKER_PORT_2375_TCP " ]; then
4+ DOCKER_SOCK=/var/run/docker.sock
5+ CRONTAB_FILE=/etc/crontabs/docker
6+
7+ # For local testing only.
8+ # HOME_DIR=.
9+
10+ if [ -z " ${HOME_DIR} " ]; then
11+ echo " HOME_DIR not set."
12+ exit 1
13+ fi
14+
15+ # Ensure dir exist - in case of volume mapping.
16+ mkdir -p " ${HOME_DIR} " /jobs " ${HOME_DIR} " /projects
17+
18+ if [ -z " ${DOCKER_HOST} " ] && [ -a " ${DOCKER_PORT_2375_TCP} " ]; then
519 export DOCKER_HOST=' tcp://docker:2375'
620fi
721
8- # for local testing only
9- # HOME_DIR=.
1022
1123if [ " ${LOG_FILE} " == " " ]; then
1224 LOG_DIR=/var/log/crontab
@@ -15,88 +27,80 @@ if [ "${LOG_FILE}" == "" ]; then
1527 touch ${LOG_FILE}
1628fi
1729
18- get_config () {
30+ normalize_config () {
31+ JSON_CONFIG={}
1932 if [ -f " ${HOME_DIR} /config.json" ]; then
20- jq ' map(.) ' ${HOME_DIR} /config.json > ${HOME_DIR} /config.working.json
33+ JSON_CONFIG= " $( cat " ${HOME_DIR} " /config.json) "
2134 elif [ -f " ${HOME_DIR} /config.toml" ]; then
22- rq -t <<< $( cat ${HOME_DIR} /config.toml) | jq ' map(.) ' > ${HOME_DIR} /config.json
35+ JSON_CONFIG= " $( rq -t <<< " $(cat " ${HOME_DIR} " /config.toml)" ) "
2336 elif [ -f " ${HOME_DIR} /config.yml" ]; then
24- rq -y <<< $( cat ${HOME_DIR} /config.yml) | jq ' map(.) ' > ${HOME_DIR} /config.json
37+ JSON_CONFIG= " $( rq -y <<< " $(cat " ${HOME_DIR} " /config.yml)" ) "
2538 elif [ -f " ${HOME_DIR} /config.yaml" ]; then
26- rq -y <<< $( cat ${HOME_DIR} /config.yaml) | jq ' map(.) ' > ${HOME_DIR} /config.json
39+ JSON_CONFIG= " $( rq -y <<< " $(cat " ${HOME_DIR} " /config.yaml)" ) "
2740 fi
41+ jq ' map(.)' " ${JSON_CONFIG} " > " ${HOME_DIR} " /config.working.json
2842}
2943
30- DOCKER_SOCK=/var/run/docker.sock
31- CRONTAB_FILE=/etc/crontabs/docker
32-
33- # Ensure dir exist - in case of volume mapping
34- mkdir -p ${HOME_DIR} /jobs ${HOME_DIR} /projects
35-
3644ensure_docker_socket_accessible () {
3745 if ! grep -q " ^docker:" /etc/group; then
38- # Ensure 'docker' user has permissions for docker socket (without changing permissions)
46+ # Ensure 'docker' user has permissions for docker socket (without changing permissions).
3947 DOCKER_GID=$( stat -c ' %g' ${DOCKER_SOCK} )
4048 if [ " ${DOCKER_GID} " != " 0" ]; then
4149 if ! grep -qE " ^[^:]+:[^:]+:${DOCKER_GID} :" /etc/group; then
42- # No group with such gid exists - create group docker
43- addgroup -g ${DOCKER_GID} docker
50+ # No group with such gid exists - create group docker.
51+ addgroup -g " ${DOCKER_GID} " docker
4452 adduser docker docker
4553 else
46- # Group with such gid exists - add user "docker" to this group
47- DOCKER_GROUP_NAME=` getent group " ${DOCKER_GID} " | awk -F' :' ' {{ print $1 }}' `
48- adduser docker $ DOCKER_GROUP_NAME
54+ # Group with such gid exists - add user "docker" to this group.
55+ DOCKER_GROUP_NAME=$( getent group " ${DOCKER_GID} " | awk -F' :' ' {{ print $1 }}' )
56+ adduser docker " ${ DOCKER_GROUP_NAME} "
4957 fi
5058 else
51- # Docker socket belongs to "root" group - add user "docker" to this group
59+ # Docker socket belongs to "root" group - add user "docker" to this group.
5260 adduser docker root
5361 fi
5462 fi
5563}
5664
5765slugify () {
58- echo " $@ " | iconv -t ascii | sed -r s/[~\ ^ ]+//g | sed -r s/[^a-zA-Z0-9]+/-/g | sed -r s/^-+\| -+$//g | tr A-Z a-z
66+ echo " ${ @ } " | iconv -t ascii | sed -r s/[~^]+//g | sed -r s/[^a-zA-Z0-9]+/-/g | sed -r s/^-+\| -+$//g | tr ' [:upper:] ' ' [:lower:] '
5967}
6068
6169make_image_cmd () {
62- DOCKERARGS=$( echo ${1} | jq -r .dockerargs)
63- VOLUMES=$( echo ${1} | jq -r ' .volumes | map(" -v " + .) | join("")' )
64- PORTS=$( echo ${1} | jq -r ' .ports | map(" -p " + .) | join("")' )
65- EXPOSE=$( echo ${1} | jq -r ' .expose | map(" --expose " + .) | join("")' )
66- # We'll add name in, if it exists
67- NAME=$( echo ${1} | jq -r ' select(.name != null) | .name' )
68- NETWORK=$( echo ${1} | jq -r ' select(.network != null) | .network' )
69- ENVIRONMENT=$( echo ${1} | jq -r ' .environment | map(" -e " + .) | join("")' )
70- # echo ${1} | jq -r '.environment | join("\n")' > ${PWD}/${NAME}.env
71- # ENVIRONMENT=" --env-file ${PWD}/${NAME}.env"
70+ DOCKERARGS=$( echo " ${1} " | jq -r .dockerargs)
71+ VOLUMES=$( echo " ${1} " | jq -r ' .volumes | map(" -v " + .) | join("")' )
72+ PORTS=$( echo " ${1} " | jq -r ' .ports | map(" -p " + .) | join("")' )
73+ EXPOSE=$( echo " ${1} " | jq -r ' .expose | map(" --expose " + .) | join("")' )
74+ NAME=$( echo " ${1} " | jq -r ' select(.name != null) | .name' )
75+ NETWORK=$( echo " ${1} " | jq -r ' select(.network != null) | .network' )
76+ ENVIRONMENT=$( echo " ${1} " | jq -r ' .environment | map(" -e " + .) | join("")' )
7277 if [ " ${DOCKERARGS} " == " null" ]; then DOCKERARGS=; fi
73- if [ ! -z " ${NAME} " ]; then DOCKERARGS=" ${DOCKERARGS} --rm --name ${NAME} " ; fi
74- if [ ! -z " ${NETWORK} " ]; then DOCKERARGS=" ${DOCKERARGS} --network ${NETWORK} " ; fi
75- if [ ! -z " ${VOLUMES} " ]; then DOCKERARGS=" ${DOCKERARGS}${VOLUMES} " ; fi
76- if [ ! -z " ${ENVIRONMENT} " ]; then DOCKERARGS=" ${DOCKERARGS}${ENVIRONMENT} " ; fi
77- if [ ! -z " ${PORTS} " ]; then DOCKERARGS=" ${DOCKERARGS}${PORTS} " ; fi
78- if [ ! -z " ${EXPOSE} " ]; then DOCKERARGS=" ${DOCKERARGS}${EXPOSE} " ; fi
79- IMAGE=$( echo ${1} | jq -r .image | envsubst)
80- TMP_COMMAND=$( echo ${1} | jq -r .command)
78+ if [ -n " ${NAME} " ]; then DOCKERARGS=" ${DOCKERARGS} --rm --name ${NAME} " ; fi
79+ if [ -n " ${NETWORK} " ]; then DOCKERARGS=" ${DOCKERARGS} --network ${NETWORK} " ; fi
80+ if [ -n " ${VOLUMES} " ]; then DOCKERARGS=" ${DOCKERARGS}${VOLUMES} " ; fi
81+ if [ -n " ${ENVIRONMENT} " ]; then DOCKERARGS=" ${DOCKERARGS}${ENVIRONMENT} " ; fi
82+ if [ -n " ${PORTS} " ]; then DOCKERARGS=" ${DOCKERARGS}${PORTS} " ; fi
83+ if [ -n " ${EXPOSE} " ]; then DOCKERARGS=" ${DOCKERARGS}${EXPOSE} " ; fi
84+ IMAGE=$( echo " ${1} " | jq -r .image | envsubst)
85+ TMP_COMMAND=$( echo " ${1} " | jq -r .command)
8186 echo " docker run ${DOCKERARGS} ${IMAGE} ${TMP_COMMAND} "
8287}
8388
8489make_container_cmd () {
85- DOCKERARGS=$( echo ${1} | jq -r .dockerargs)
90+ DOCKERARGS=$( echo " ${1} " | jq -r .dockerargs)
8691 if [ " ${DOCKERARGS} " == " null" ]; then DOCKERARGS=; fi
87- SCRIPT_NAME=$( echo ${1} | jq -r .name)
88- SCRIPT_NAME=$( slugify $ SCRIPT_NAME)
89- PROJECT=$( echo ${1} | jq -r .project)
90- CONTAINER=$( echo ${1} | jq -r .container | envsubst)
91- TMP_COMMAND=$( echo ${1} | jq -r .command)
92+ SCRIPT_NAME=$( echo " ${1} " | jq -r .name)
93+ SCRIPT_NAME=$( slugify " ${ SCRIPT_NAME} " )
94+ PROJECT=$( echo " ${1} " | jq -r .project)
95+ CONTAINER=$( echo " ${1} " | jq -r .container | envsubst)
96+ TMP_COMMAND=$( echo " ${1} " | jq -r .command)
9297
9398 if [ " ${PROJECT} " != " null" ]; then
94-
95- # create bash script to detect all running containers
99+ # Create bash script to detect all running containers.
96100 if [ " ${SCRIPT_NAME} " == " null" ]; then
97101 SCRIPT_NAME=$( cat /proc/sys/kernel/random/uuid)
98102 fi
99- cat << EOF > ${HOME_DIR} /projects/${SCRIPT_NAME} .sh
103+ cat << EOF > " ${HOME_DIR} " /projects/" ${SCRIPT_NAME} " .sh
100104#!/usr/bin/env bash
101105set -e
102106
@@ -106,7 +110,6 @@ for CONTAINER_NAME in \$CONTAINERS; do
106110done
107111EOF
108112 echo " /bin/bash ${HOME_DIR} /projects/${SCRIPT_NAME} .sh"
109- # cat "/bin/bash ${HOME_DIR}/projects/${SCRIPT_NAME}.sh"
110113 else
111114 echo " docker exec ${DOCKERARGS} ${CONTAINER} ${TMP_COMMAND} "
112115 fi
@@ -119,14 +122,14 @@ EOF
119122# }
120123
121124make_cmd () {
122- if [ " $( echo ${1} | jq -r .image) " != " null" ]; then
123- make_image_cmd " $1 "
124- elif [ " $( echo ${1} | jq -r .container) " != " null" ]; then
125- make_container_cmd " $1 "
125+ if [ " $( echo " ${1} " | jq -r .image) " != " null" ]; then
126+ make_image_cmd " ${1} "
127+ elif [ " $( echo " ${1} " | jq -r .container) " != " null" ]; then
128+ make_container_cmd " ${1} "
126129 # elif [ "$(echo ${1} | jq -r .host)" != "null" ]; then
127- # make_host_cmd "$1 "
130+ # make_host_cmd "${1} "
128131 else
129- echo ${1} | jq -r .command
132+ echo " ${1} " | jq -r .command
130133 fi
131134}
132135
@@ -157,18 +160,18 @@ parse_schedule() {
157160 TIME=$2
158161 TOTAL=0
159162
160- M=$( echo $ TIME | grep -o ' [0-9]\+m' )
161- H=$( echo $ TIME | grep -o ' [0-9]\+h' )
162- D=$( echo $ TIME | grep -o ' [0-9]\+d' )
163+ M=$( echo " ${ TIME} " | grep -o ' [0-9]\+m' )
164+ H=$( echo " ${ TIME} " | grep -o ' [0-9]\+h' )
165+ D=$( echo " ${ TIME} " | grep -o ' [0-9]\+d' )
163166
164167 if [ -n " ${M} " ]; then
165- TOTAL=$(( $ TOTAL + ${M::- 1} ))
168+ TOTAL=$(( TOTAL + ${M::- 1} ))
166169 fi
167170 if [ -n " ${H} " ]; then
168- TOTAL=$(( $ TOTAL + ${H::- 1} * 60 ))
171+ TOTAL=$(( TOTAL + ${H::- 1} * 60 ))
169172 fi
170173 if [ -n " ${D} " ]; then
171- TOTAL=$(( $ TOTAL + ${D::- 1} * 60 * 24 ))
174+ TOTAL=$(( TOTAL + ${D::- 1} * 60 * 24 ))
172175 fi
173176
174177 echo " */${TOTAL} * * * *"
@@ -180,73 +183,64 @@ parse_schedule() {
180183}
181184
182185function build_crontab() {
183-
184186 rm -rf ${CRONTAB_FILE}
185187
186188 ONSTART=()
187- while read i ; do
189+ while read -r i ; do
188190
189- SCHEDULE=$( jq -r .[$i ].schedule ${CONFIG} | sed ' s/\*/\\*/g' )
191+ SCHEDULE=$( jq -r .[" $i " ].schedule " ${CONFIG} " | sed ' s/\*/\\*/g' )
190192 if [ " ${SCHEDULE} " == " null" ]; then
191- echo " Schedule Missing: $( jq -r .[$i ].schedule ${CONFIG} ) "
193+ echo " Schedule Missing: $( jq -r .[" $i " ].schedule " ${CONFIG} " ) "
192194 continue
193195 fi
194- SCHEDULE=$( parse_schedule ${SCHEDULE} | sed ' s/\\//g' )
196+ SCHEDULE=$( parse_schedule " ${SCHEDULE} " | sed ' s/\\//g' )
195197
196- if [ " $( jq -r .[$i ].command ${CONFIG} ) " == " null" ]; then
197- echo " Command Missing: $( jq -r .[$i ].command ${CONFIG} ) "
198+ COMMAND=$( jq -r .[" $i " ].command " ${CONFIG} " )
199+ if [ " ${COMMAND} " == " null" ]; then
200+ echo " Command Missing: '${COMMAND} '"
198201 continue
199202 fi
200203
201- COMMENT=$( jq -r .[$i ].comment ${CONFIG} )
204+ COMMENT=$( jq -r .[" $i " ].comment " ${CONFIG} " )
202205 if [ " ${COMMENT} " != " null" ]; then
203206 echo " # ${COMMENT} " >> ${CRONTAB_FILE}
204207 fi
205208
206- SCRIPT_NAME=$( jq -r .[$i ].name ${CONFIG} )
207- SCRIPT_NAME=$( slugify $ SCRIPT_NAME)
209+ SCRIPT_NAME=$( jq -r .[" $i " ].name " ${CONFIG} " )
210+ SCRIPT_NAME=$( slugify " ${ SCRIPT_NAME} " )
208211 if [ " ${SCRIPT_NAME} " == " null" ]; then
209212 SCRIPT_NAME=$( cat /proc/sys/kernel/random/uuid)
210213 fi
211214
212215 COMMAND=" /bin/bash ${HOME_DIR} /jobs/${SCRIPT_NAME} .sh"
213- cat << EOF > ${HOME_DIR} /jobs/${SCRIPT_NAME} .sh
216+ cat << EOF > " ${HOME_DIR} " /jobs/" ${SCRIPT_NAME} " .sh
214217#!/usr/bin/env bash
215218set -e
216219
217- # TODO find workaround
218- # [error] write /dev/stdout: broken pipe <- when using docker commands
219- #UUID=\$ (cat /proc/sys/kernel/random/uuid)
220- #exec > >(read message; echo "\$ {UUID} \$ (date -Iseconds) [info] \$ message" | tee -a ${LOG_FILE} )
221- #exec 2> >(read message; echo "\$ {UUID} \$ (date -Iseconds) [error] \$ message" | tee -a ${LOG_FILE} >&2)
222-
223220echo "Start Cronjob **${SCRIPT_NAME} ** ${COMMENT} "
224221
225- $( make_cmd " $( jq -c .[$i ] ${CONFIG} ) " )
222+ $( make_cmd " $( jq -c .[" $i " ] " ${CONFIG} " ) " )
226223EOF
227-
228-
229-
230- if [ " $( jq -r .[$i ].trigger ${CONFIG} ) " != " null" ]; then
231- while read j ; do
232- if [ " $( jq .[$i ].trigger[$j ].command ${CONFIG} ) " == " null" ]; then
233- echo " Command Missing: $( jq -r .[$i ].trigger[$j ].command ${CONFIG} ) "
224+ TRIGGER=$( jq -r .[" $i " ].trigger " ${CONFIG} " )
225+ if [ " ${TRIGGER} " != " null" ]; then
226+ while read -r j ; do
227+ TRIGGER_COMMAND=$( jq .[" $i " ].trigger[" $j " ].command " ${CONFIG} " )
228+ if [ " ${TRIGGER_COMMAND} " == " null" ]; then
229+ echo " Command Missing: '${TRIGGER_COMMAND} '"
234230 continue
235231 fi
236- # TRIGGER_COMMAND=$(make_cmd "$(jq -c .[$i].trigger[$j] ${CONFIG})")
237- echo " $( make_cmd " $( jq -c .[$i ].trigger[$j ] ${CONFIG} ) " ) " >> ${HOME_DIR} /jobs/${SCRIPT_NAME} .sh
238- # COMMAND="${COMMAND} && ${TRIGGER_COMMAND}"
239- done < <( jq -r ' .[' $i ' ].trigger|keys[]' ${CONFIG} )
232+ make_cmd " ${TRIGGER_COMMAND} " >> " ${HOME_DIR} " /jobs/" ${SCRIPT_NAME} " .sh
233+ done < <( jq -r ' .[' " $i " ' ].trigger|keys[]' " ${CONFIG} " )
240234 fi
241235
242- echo " echo \" End Cronjob **${SCRIPT_NAME} ** ${COMMENT} \" " >> ${HOME_DIR} /jobs/${SCRIPT_NAME} .sh
236+ echo " echo \" End Cronjob **${SCRIPT_NAME} ** ${COMMENT} \" " >> " ${HOME_DIR} " /jobs/" ${SCRIPT_NAME} " .sh
243237
244238 echo " ${SCHEDULE} ${COMMAND} " >> ${CRONTAB_FILE}
245239
246- if [ " $( jq -r .[$i ].onstart ${CONFIG} ) " == " true" ]; then
240+ if [ " $( jq -r .[" $i " ].onstart " ${CONFIG} " ) " == " true" ]; then
247241 ONSTART+=(" ${COMMAND} " )
248242 fi
249- done < <( jq -r ' .|keys[]' ${CONFIG} )
243+ done < <( jq -r ' .|keys[]' " ${CONFIG} " )
250244
251245 echo " ##### crontab generation complete #####"
252246 cat ${CRONTAB_FILE}
@@ -258,27 +252,19 @@ EOF
258252 done
259253}
260254
261-
262- ensure_docker_socket_accessible
263-
264255start_app () {
265- get_config
266- if [ -f " ${HOME_DIR} /config.working.json" ]; then
267- export CONFIG=${HOME_DIR} /config.working.json
268- elif [ -f " ${HOME_DIR} /config.json" ]; then
269- export CONFIG=${HOME_DIR} /config.json
270- else
271- echo " NO CONFIG FILE FOUND"
256+ normalize_config
257+ export CONFIG=${HOME_DIR} /config.working.json
258+ if [ ! -f " ${CONFIG} " ]; then
259+ echo " Unable to find ${CONFIG} ."
260+ exit 1
272261 fi
273- if [ " $1 " = " crond" ]; then
274- if [ -f ${CONFIG} ]; then
275- build_crontab
276- else
277- echo " Unable to find ${CONFIG} "
278- fi
262+ if [ " ${1} " == " crond" ]; then
263+ build_crontab
279264 fi
280- echo " $@ "
281- exec " $@ "
265+ echo " ${ @ } "
266+ exec " ${ @ } "
282267}
283268
284- start_app " $@ "
269+ ensure_docker_socket_accessible
270+ start_app " ${@ } "
0 commit comments