From ed719701538b6f1b1f9237c9cd5b2c76c0713628 Mon Sep 17 00:00:00 2001 From: Kevin Baensch Date: Fri, 16 Dec 2022 14:17:11 +0100 Subject: [PATCH] [WIP] Docker templater mostly working (to be squashed) --- docker-compose.yml | 14 +++++++--- script/docker-templater.sh | 20 ++++++-------- script/hostman.sh | 53 ++++++++++++++------------------------ script/sqlproxy.sh | 2 +- templates/caddy.sh | 21 +++++++++++++-- templates/hosts.sh | 6 ++--- templates/sqlproxy.sh | 17 +++++++++++- 7 files changed, 77 insertions(+), 56 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index b99048e..f16e64a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,19 +2,25 @@ version: "3.4" services: hostman: - image: apteno/alpine-jq + image: julienlecomte/docker-make command: ["./hostman.sh", "&", "wait", "$!" ] volumes: - /var/run/docker.sock:/tmp/docker.sock:ro - - /etc/hosts:/tmp/hosts:rw + - /etc/hosts:/config/hosts:rw - ./script/hostman.sh:/hostman.sh:ro - nginx-proxy: - image: jwilder/nginx-proxy + - ./script/docker-templater.sh:/docker-templater.sh:ro + - ./templates:/templates + - ./config:/config + networks: + - proxy + proxy: + image: caddy:2.6.2-alpine ports: - "80:80" - "443:443" volumes: - /var/run/docker.sock:/tmp/docker.sock:ro + - ./config/Caddyfile:/etc/caddy/Caddyfile networks: - proxy diff --git a/script/docker-templater.sh b/script/docker-templater.sh index a3081f8..0fbf905 100755 --- a/script/docker-templater.sh +++ b/script/docker-templater.sh @@ -55,7 +55,7 @@ fi for row in $(jq -r '.[] | @base64' <<< "${DOCKER_DATA}") do - CONTAINER_DATA=$(base64 --decode <<< "${row}"); + CONTAINER_DATA=$(base64 -d <<< "${row}"); # Set non Label values if [ -z "${LOCAL_IP}" ] then @@ -91,7 +91,7 @@ do if template_hook then # FIX with printf - RESULT+="${PARTIAL_RESULT}" + RESULT=$(printf '%s' "${RESULT}" "${RESULT:+$SEPARATOR}" "${PARTIAL_RESULT}") fi else RESULT=$(printf '%s' "${RESULT}" "${RESULT:+$SEPARATOR}" "${PARTIAL_RESULT}") @@ -100,23 +100,19 @@ do # Unset label-environment variables for next container for var in $(envsubst -v "${TEMPLATE}") do - if [ "${var}" != "LOCAL_IP" ] - then - unset "${!var}" - fi + unset "${var}" done done -RESULT="${WRAP_START}${RESULT}${WRAP_END}" - +RESULT="$(printf "%b" "${WRAP_START}" "${RESULT}" "${WRAP_END}")" if [ -z "${OUT}" ] then - printf "%b\n" "${RESULT}"; + printf "%b" "${RESULT}"; else - if ! diff --brief "${OUT}" - > /dev/null 2>&1 <<< "${RESULT}" + if [ "$(cat "${OUT}")" != "${RESULT}" ] then - printf "Template Task: '%s' has been written to: '%s'\n" "${TEMPLATE_SRC}" "${OUT}" - printf "%b\n" "${RESULT}" > "${OUT}"; + printf "%s | Template Task: '%s' has been written to: '%s'\n" "$(date --iso-8601)" "${TEMPLATE_SRC}" "${OUT}" + printf "%b" "${RESULT}" > "${OUT}"; fi fi diff --git a/script/hostman.sh b/script/hostman.sh index f48a442..3c1340c 100755 --- a/script/hostman.sh +++ b/script/hostman.sh @@ -1,46 +1,33 @@ #!/usr/bin/env sh + # Configurable Variables -[ -z $DOCKER_SOCK_PATH ] && DOCKER_SOCK_PATH="/tmp/docker.sock" -[ -z $NETWORK_NAME ] && NETWORK_NAME="proxy" -[ -z $RESOLVE_DOCKERHOST ] && RESOLVE_DOCKERHOST=false -[ -z $HOST_CONF_PATH ] && HOST_CONF_PATH="/tmp/hosts" -[ -z $DOCKER_HOSTNAME_VAR ] && DOCKER_HOSTNAME_VAR="VIRTUAL_HOST" +DOCKER_SOCK_PATH="${DOCKER_SOCK_PATH:-/tmp/docker.sock}" +NETWORK_NAME="${NETWORK_NAME:-proxy}" +TEMPLATER_PATH="${TEMPLATER_PATH:-/docker-templater.sh}" +TEMPLATE_FOLDER_PATH="${TEMPLATE_FOLDER_PATH:-/templates}" query_docker () { curl --unix-socket $DOCKER_SOCK_PATH --silent -g http://v1.41/$1$2 } -get_host_list() { - PROXY_HOST_CONF="" - CONTAINER_LIST=$(query_docker "containers/json" "?filters={%22network%22:[%22${NETWORK_NAME}%22],%22status%22:[%22running%22]}" | jq -cr '.[].Id') - - for id in $CONTAINER_LIST - do - # Query individual container to access relevant data - CONTAINER_DATA=$(query_docker "containers/${id}/json") - if $RESOLVE_DOCKERHOST - then - HOST_IP=$(echo $CONTAINER_DATA | jq -cr '.NetworkSettings.Networks.proxy.IPAddress') - else - HOST_IP="127.0.0.1" - fi - # Filter Env for HOSTNAME, remove list parenthesis and split/only keep values - HOST_NAMES=$(echo $CONTAINER_DATA | jq -cr ".Config.Env[] | select(contains(\"$DOCKER_HOSTNAME_VAR=\")) | split(\"=\")[1]") - - for hostname in $HOST_NAMES +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}" ] + then + for template in "${TEMPLATE_FOLDER_PATH}"/* do - PROXY_HOST_CONF="$PROXY_HOST_CONF\n$HOST_IP $hostname # Added by hostman" + if ! "${TEMPLATER_PATH}" "${template}" "${CONTAINER_LIST}" + then + echo "Error Processing Template: ${template}" + fi done - done - echo $PROXY_HOST_CONF + OLD_CONTAINER_LIST="${CONTAINER_LIST}" + fi } -update_host_list() { - FILTERED_HOSTS=$(grep -ve "# Added by hostman$" $HOST_CONF_PATH) - echo -e "$FILTERED_HOSTS$(get_host_list)" > $HOST_CONF_PATH -} +# Initial Generation +update_templates -update_host_list # cannot filter because reailine no longer recognized lines otherwise (check how IFS changes) query_docker "events" | while true do @@ -48,7 +35,7 @@ do # wait for related events to finish while [ $? -eq 0 ] do - read -t 5 -r; + read -t 8 -r done - update_host_list + update_templates done diff --git a/script/sqlproxy.sh b/script/sqlproxy.sh index 90be21b..63a55c2 100755 --- a/script/sqlproxy.sh +++ b/script/sqlproxy.sh @@ -5,4 +5,4 @@ chown -R sqlproxy:sqlproxy /etc/ssh/.ssh chmod 0700 /etc/ssh/.ssh chmod 0600 /etc/ssh/.ssh/authorized_keys -source ./hostman.sh +sleep infinity diff --git a/templates/caddy.sh b/templates/caddy.sh index 7d5dc52..1b9dc2d 100644 --- a/templates/caddy.sh +++ b/templates/caddy.sh @@ -1,16 +1,33 @@ #!/usr/bin/env bash set -e +DOCKER_SOCK_PATH="${DOCKER_SOCK_PATH:-/tmp/docker.sock}" +DOCKER_CADDY_NAME="${DOCKER_CADDY_NAME:-proxy}" +DOCKER_CADDY_PORT="${DOCKER_CADDY_PORT:-2020}" -TEMPLATE='reverse_proxy $LOCAL_WEB_HOST ${LOCAL_IP}:$LOCAL_WEB_PORT' +WRAP_START='{\n admin :2020\n}\n' +WRAP_END='\n' +TEMPLATE='${LOCAL_WEB_HOST} {\n reverse_proxy ${LOCAL_IP}:$LOCAL_WEB_PORT\n}' +SEPARATOR='\n' +OUT='/config/Caddyfile' label_hook() { LOCAL_WEB_PORT="${LOCAL_WEB_PORT:-80}" } template_hook() { - if grep -q '^reverse_proxy [^\s] [:.0-9a-e]\+:\d+$' <<< "${PARTIAL_RESULT}" + printf "%s" "${PARTIAL_RESULT}" + if grep '^[^ ]\+ {\\n reverse_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 +# } diff --git a/templates/hosts.sh b/templates/hosts.sh index 2a04f5b..810440c 100644 --- a/templates/hosts.sh +++ b/templates/hosts.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash set -e -HOST_CONF_PATH="${HOST_CONF_PATH:-/tmp/hosts}" +HOST_CONF_PATH="${HOST_CONF_PATH:-/config/hosts}" RESOLVE_DOCKERHOST="${RESOLVE_DOCKERHOST:-false}" DOCKER_HOSTNAME_VAR="${DOCKER_HOSTNAME_VAR:-LOCAL_WEB_HOST}" @@ -31,8 +31,8 @@ else OUT="${HOST_CONF_OUT}" fi -check_template() { - if grep -q '^[:.0-9a-e]\+ [^\s]\+ # Added by hostman$' <<< "${PARTIAL_RESULT}" +template_hook() { + if grep -q '^[:.0-9a-e]\+ [^ ]\+ # Added by hostman$' <<< "${PARTIAL_RESULT}" then return 0; fi diff --git a/templates/sqlproxy.sh b/templates/sqlproxy.sh index 614064a..5ed4ad3 100644 --- a/templates/sqlproxy.sh +++ b/templates/sqlproxy.sh @@ -1,6 +1,21 @@ #!/usr/bin/env bash +EXCLUDE_USERPASS="${EXCLUDE_USERPASS:-false}" set -e WRAP_START='[\n' -TEMPLATE=' { type: "${LOCAL_DB_TYPE}", user: "${LOCAL_DB_USER}", password: "${LOCAL_DB_PASSWORD}", host: "${LOCAL_DB_HOST}", port: "${LOCAL_DB_PORT}" }' +if ${EXCLUDE_USERPASS} +then + 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}" }' +fi SEPARATOR=',\n' WRAP_END='\n]' +OUT="/config/sqlproxy.json" + +template_hook() { + if grep -q 'type: "(?mysql|psql)".*host: ".+", port: "\d+"' + then + return 0 + fi + return 1 +}