diff --git a/docker-compose.yml b/docker-compose.yml index f16e64a..9cd3bb8 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -6,11 +6,11 @@ services: command: ["./hostman.sh", "&", "wait", "$!" ] volumes: - /var/run/docker.sock:/tmp/docker.sock:ro - - /etc/hosts:/config/hosts:rw - ./script/hostman.sh:/hostman.sh:ro - ./script/docker-templater.sh:/docker-templater.sh:ro - - ./templates:/templates - - ./config:/config + - ./templates:/templates:ro + - ./config:/config:rw + - /etc/hosts:/config/hosts:rw networks: - proxy proxy: @@ -19,8 +19,8 @@ services: - "80:80" - "443:443" volumes: - - /var/run/docker.sock:/tmp/docker.sock:ro - - ./config/Caddyfile:/etc/caddy/Caddyfile + - ./config/Caddyfile:/etc/caddy/Caddyfile:ro + - ./caddy_data:/data/caddy networks: - proxy diff --git a/script/docker-templater.sh b/script/docker-templater.sh index 0fbf905..341b385 100755 --- a/script/docker-templater.sh +++ b/script/docker-templater.sh @@ -6,7 +6,9 @@ DOCKER_DATA=$2; NETWORK_NAME="${NETWORK_NAME:-proxy}" -# "NetworkSettings" +get_date() { + printf '%s' "$(date +'%Y.%m.%d_%H:%M:%S')" +} # Import Template # Required Variables: @@ -19,17 +21,18 @@ NETWORK_NAME="${NETWORK_NAME:-proxy}" # Optional Functions: # - label_hook :: modify/override label query results # - template_hook :: hook to verify/modify template rsults (0 => OK; 1 => SKIP) +# - finally_hook :: gets executed after (and also only if) the final result has been written to disk if [ -f "${TEMPLATE_SRC}" ] then source "${TEMPLATE_SRC}" if [ -z "${TEMPLATE}" ] then - echo "[ERR]: Template \"${TEMPLATE_SRC}\" does define a template string." + printf '%s | [ERR]: Template "%s" does define a template string.\n' "$(get_date)" "${TEMPLATE_SRC}" exit 1 fi else - echo "[ERR]: No such File \"${TEMPLATE_SRC}\"."; + printf '%s | [ERR]: No such File "%s".\n' "$(get_date)" "${TEMPLATE_SRC}"; exit 1 fi @@ -48,6 +51,14 @@ else RUN_TEMPLATE_HOOK=false fi +if type finally_hook 2>/dev/null | grep -q "finally_hook is a function" +then + RUN_FINALLY_HOOK=true +else + RUN_FINALLY_HOOK=false +fi + + if [ -z "${SEPARATOR+.}" ] then SEPARATOR='\n' @@ -104,15 +115,19 @@ do done done -RESULT="$(printf "%b" "${WRAP_START}" "${RESULT}" "${WRAP_END}")" +RESULT="$(printf "%s" "${WRAP_START}" "${RESULT}" "${WRAP_END}")" if [ -z "${OUT}" ] then printf "%b" "${RESULT}"; else - if [ "$(cat "${OUT}")" != "${RESULT}" ] + if [ "$(cat "${OUT}")" != "$(printf '%b'"${RESULT}")" ] then - printf "%s | Template Task: '%s' has been written to: '%s'\n" "$(date --iso-8601)" "${TEMPLATE_SRC}" "${OUT}" + printf "%s | Template Task: '%s' has been written to: '%s'\n" "$(get_date)" "${TEMPLATE_SRC}" "${OUT}" printf "%b" "${RESULT}" > "${OUT}"; + if ${RUN_FINALLY_HOOK} + then + finally_hook + fi fi fi diff --git a/script/hostman.sh b/script/hostman.sh index 3c1340c..1cd5f37 100755 --- a/script/hostman.sh +++ b/script/hostman.sh @@ -6,22 +6,31 @@ NETWORK_NAME="${NETWORK_NAME:-proxy}" TEMPLATER_PATH="${TEMPLATER_PATH:-/docker-templater.sh}" TEMPLATE_FOLDER_PATH="${TEMPLATE_FOLDER_PATH:-/templates}" +get_date() { + printf '%s' "$(date +'%Y.%m.%d_%H:%M:%S')" +} + query_docker () { curl --unix-socket $DOCKER_SOCK_PATH --silent -g http://v1.41/$1$2 } update_templates() { CONTAINER_LIST=$(query_docker "containers/json" "?filters={%22network%22:[%22${NETWORK_NAME}%22],%22status%22:[%22running%22]}") - if [ "${CONTAINER_LIST}" != "${OLD_CONTAINER_LIST}" ] + LABELS_NEW="$(echo "${CONTAINER_LIST}" | jq '.[].Labels | @base64' | sort)" + if [ "${LABELS_NEW}" != "${LABELS_OLD}" ] then + if [ -n "${LABELS_OLD}" ] + then + printf '%s | Container label list change detected.\n' "$(get_date)" + fi + LABELS_OLD="${LABELS_NEW}" for template in "${TEMPLATE_FOLDER_PATH}"/* do if ! "${TEMPLATER_PATH}" "${template}" "${CONTAINER_LIST}" then - echo "Error Processing Template: ${template}" + printf '%s | Error Processing Template: %s\n' "$(get_date)" "${template}" fi done - OLD_CONTAINER_LIST="${CONTAINER_LIST}" fi } @@ -31,11 +40,14 @@ update_templates # cannot filter because reailine no longer recognized lines otherwise (check how IFS changes) query_docker "events" | while true do + printf '%s | Listening for docker events\n' "$(get_date)" read -r; # wait for related events to finish + printf '%s | Waiting for event messages to settle.\n' "$(get_date)" while [ $? -eq 0 ] do read -t 8 -r done + printf '%s | Checking for changes in container label list.\n' "$(get_date)" update_templates done diff --git a/templates/caddy.sh b/templates/caddy.sh index 1b9dc2d..ea4c62a 100644 --- a/templates/caddy.sh +++ b/templates/caddy.sh @@ -4,9 +4,9 @@ DOCKER_SOCK_PATH="${DOCKER_SOCK_PATH:-/tmp/docker.sock}" DOCKER_CADDY_NAME="${DOCKER_CADDY_NAME:-proxy}" DOCKER_CADDY_PORT="${DOCKER_CADDY_PORT:-2020}" -WRAP_START='{\n admin :2020\n}\n' +WRAP_START='{\n\tadmin :2020\n}\n' WRAP_END='\n' -TEMPLATE='${LOCAL_WEB_HOST} {\n reverse_proxy ${LOCAL_IP}:$LOCAL_WEB_PORT\n}' +TEMPLATE='${LOCAL_WEB_HOST} {\n\treverse_proxy ${LOCAL_IP}:$LOCAL_WEB_PORT\n}' SEPARATOR='\n' OUT='/config/Caddyfile' @@ -15,19 +15,18 @@ label_hook() { } template_hook() { - printf "%s" "${PARTIAL_RESULT}" - if grep '^[^ ]\+ {\\n reverse_proxy \(?::\|[.0-9a-e]\)\+\:[0-9]\+\\n}$' <<< "${PARTIAL_RESULT}" + if grep -q '^[^ ]\+ {\\n\\treverse_proxy \(?::\|[.0-9a-e]\)\+\:[0-9]\+\\n}$' <<< "${PARTIAL_RESULT}" then return 0; fi return 1; } -# finally_hook() { -# if curl --silent -g "${DOCKER_CADDY_NAME}:${DOCKER_CADDY_PORT}/load" -# then -# printf "Updated Caddy Config" -# else -# printf "Failed to update Caddy Config" -# fi -# } +finally_hook() { + if curl --silent "${DOCKER_CADDY_NAME}:${DOCKER_CADDY_PORT}/load" -H "Content-Type: text/caddyfile" --data-binary "@${OUT}" + then + printf '%s | Updated Caddy Config\n' "$(get_date)" + else + printf '%s | Failed to update Caddy Config\n' "$(get_date)" + fi +} diff --git a/templates/sqlproxy.sh b/templates/sqlproxy.sh index 5ed4ad3..f94ba76 100644 --- a/templates/sqlproxy.sh +++ b/templates/sqlproxy.sh @@ -4,16 +4,16 @@ set -e WRAP_START='[\n' if ${EXCLUDE_USERPASS} then - TEMPLATE=' { type: "${LOCAL_DB_TYPE}", host: "${LOCAL_DB_HOST}", port: "${LOCAL_DB_PORT}" }' + TEMPLATE=' { "type": "${LOCAL_DB_TYPE}", "host": "${LOCAL_DB_HOST}", "port": "${LOCAL_DB_PORT}" }' else - TEMPLATE=' { type: "${LOCAL_DB_TYPE}", user: "${LOCAL_DB_USER}", password: "${LOCAL_DB_PASSWORD}", host: "${LOCAL_DB_HOST}", port: "${LOCAL_DB_PORT}" }' + TEMPLATE=' { "type": "${LOCAL_DB_TYPE}", "user": "${LOCAL_DB_USER}", "password": "${LOCAL_DB_PASSWORD}", "host": "${LOCAL_DB_HOST}", "port": "${LOCAL_DB_PORT}" }' fi SEPARATOR=',\n' WRAP_END='\n]' OUT="/config/sqlproxy.json" template_hook() { - if grep -q 'type: "(?mysql|psql)".*host: ".+", port: "\d+"' + if grep -q '"type": "(?mysql|psql)".*"host": ".+", port: "\d+"' <<< "${PARTIAL_RESULT}" then return 0 fi