diff --git a/.github/workflows/compose-test_docker.sock.yml b/.github/workflows/compose-test_docker_sock.yml
similarity index 90%
rename from .github/workflows/compose-test_docker.sock.yml
rename to .github/workflows/compose-test_docker_sock.yml
index d57bc32..68e6f41 100644
--- a/.github/workflows/compose-test_docker.sock.yml
+++ b/.github/workflows/compose-test_docker_sock.yml
@@ -1,4 +1,4 @@
-name: "Docker Compose Test (docker.sock)"
+name: "Docker Compose Test (docker_sock)"
on:
pull_request:
@@ -9,7 +9,7 @@ on:
- cron: "0 8 * * *"
env:
- TARGET_SERVICE: docker.sock
+ TARGET_SERVICE: docker_sock
TARGET_TIMEOUT: 15
jobs:
diff --git a/.github/workflows/compose-test_kodi.db.yml b/.github/workflows/compose-test_kodi_db.yml
similarity index 93%
rename from .github/workflows/compose-test_kodi.db.yml
rename to .github/workflows/compose-test_kodi_db.yml
index 7d2ec46..f80d961 100644
--- a/.github/workflows/compose-test_kodi.db.yml
+++ b/.github/workflows/compose-test_kodi_db.yml
@@ -1,4 +1,4 @@
-name: "Docker Compose Test (Kodi.DB)"
+name: "Docker Compose Test (Kodi_DB)"
on:
pull_request:
@@ -9,7 +9,7 @@ on:
- cron: "0 8 * * *"
env:
- TARGET_SERVICE: kodi.db
+ TARGET_SERVICE: kodi_db
TARGET_TIMEOUT: 60
jobs:
diff --git a/README.md b/README.md
index b47341e..ebd9d24 100644
--- a/README.md
+++ b/README.md
@@ -111,8 +111,8 @@ Options: { yes | no }
ignores options*.conf and uses all 'docker-compose.*.{sh,yml}' files.
Compositions Found (18):
- airdcpp certbot docker.sock gitea hass indexarr
- influxdb kodi.db monitarr navidrome nextcloud pihole
+ airdcpp certbot docker_sock gitea hass indexarr
+ influxdb kodi_db monitarr navidrome nextcloud pihole
qbittorrent tang telegraf teslamate traefik unifi
```
@@ -229,11 +229,11 @@ Compositions Found (18):
- docker.sock
+ docker_sock
-
-
+
|
A
@@ -466,7 +466,7 @@ Compositions Found (18):
:3306
-
+
|
B
diff --git a/_scripts/colors.sh b/_scripts/colors.sh
index 6c1c381..2824489 100644
--- a/_scripts/colors.sh
+++ b/_scripts/colors.sh
@@ -1,6 +1,11 @@
#!/usr/bin/env bash
+set -Eumo pipefail
+
+DISABLE_COLORS=${DISABLE_COLORS:-}
+
function P () {
+ [ -z "$DISABLE_COLORS" ] || return 0
tput "$@" 2>/dev/null
}
diff --git a/_scripts/test_comp.sh b/_scripts/test_comp.sh
index dc349c7..458be3d 100755
--- a/_scripts/test_comp.sh
+++ b/_scripts/test_comp.sh
@@ -19,7 +19,7 @@ mkdir -p "$TEST_COMP_TMP_PATH"
# SETUP
function SETUP () {
- echo -e "\n${_fg_white_}${_bg_black_}${_bold_}[#]${_normal_} Test $1: "
+ echo -e "\n${_fg_white_}${_bg_black_}${_bold_} T ${_normal_} Test $1: "
local io_path_prefix="$TEST_COMP_TMP_PATH/$1"
COMP_ERR_PATH="$io_path_prefix.err"
@@ -30,7 +30,7 @@ function SETUP () {
echo "INPUT: $3"
fi
- ./comp $2 >"$COMP_OUT_PATH" 2>"$COMP_ERR_PATH" <<<"$3"
+ DISABLE_COLORS=1 ./comp $2 >"$COMP_OUT_PATH" 2>"$COMP_ERR_PATH" <<<"$3"
COMP_EXIT_CODE=$?
if [ -n "$DEBUG" ]; then
echo "\$COMP_ERR_PATH contents:"
@@ -52,8 +52,6 @@ function CHECK {
fi
}
-./comp status tang &> /dev/null
-
SETUP "invocation without args" \
"" \
""
@@ -63,29 +61,84 @@ CHECK $'[ $COMP_EXIT_CODE -eq $EXIT_CODE_USAGE_ERROR ]' \
SETUP "status of non-existent composition" \
"status unknown_comp" \
""
+CHECK $'grep -sq "Executing status on unknown_comp" "$COMP_OUT_PATH"' \
+ "Expected info message at beginning of execution"
CHECK $'[ $COMP_EXIT_CODE -eq $EXIT_CODE_COMPOSITION_NOT_FOUND ]'\
"Expected EXIT_CODE_COMPOSITION_NOT_FOUND"
CHECK $'grep -sq "is not a base directory" "$COMP_ERR_PATH"' \
"Expected a helpful error message"
-SETUP "deny deleting data" \
+SETUP "that 'tang' is not running" \
+ "status -P tang" \
+ ""
+CHECK $'grep -sq "Executing status on tang" "$COMP_OUT_PATH"' \
+ "Expected info message at beginning of execution"
+CHECK $'grep -sq "Unhealthy service: tang" "$COMP_ERR_PATH"' \
+ "Expected error message for unhealthy service"
+CHECK $'[ $COMP_EXIT_CODE -eq $EXIT_CODE_SIMPLE_VERB_FAILURE ]' \
+ "Expected EXIT_CODE_SIMPLE_VERB_FAILURE"
+
+SETUP "starting 'tang' service without prerequisites" \
+ "up -P tang" \
+ "n"
+CHECK $'grep -sq "Executing up on tang" "$COMP_OUT_PATH"' \
+ "Expected info message at beginning of execution"
+CHECK $'[ $COMP_EXIT_CODE -eq 0 ]' \
+ "Expected EXIT_CODE = 0"
+
+SETUP "cleaning 'tang' service before stopping" \
+ "clean tang" \
+ ""
+CHECK $'grep -sq "Executing clean on tang" "$COMP_OUT_PATH"' \
+ "Expected info message at beginning of execution"
+CHECK $'grep -sq "Cannot clean while tang is running" "$COMP_ERR_PATH"' \
+ "Expected error message for running composition"
+CHECK $'[ $COMP_EXIT_CODE -eq $EXIT_CODE_SIMPLE_VERB_FAILURE ]' \
+ "Expected EXIT_CODE_SIMPLE_VERB_FAILURE"
+
+# Wait for tang to start and record health status
+sleep 15s
+
+SETUP "that 'tang' is still running" \
+ "status -P tang" \
+ ""
+CHECK $'grep -sq "Executing status on tang" "$COMP_OUT_PATH"' \
+ "Expected info message at beginning of execution"
+CHECK $'grep -sq "tang is healthy" "$COMP_OUT_PATH"' \
+ "Expected info message for healthy composition"
+CHECK $'[ $COMP_EXIT_CODE -eq 0 ]' \
+ "Expected EXIT_CODE = 0"
+
+SETUP "stopping 'tang' service" \
+ "down tang" \
+ ""
+CHECK $'grep -sq "Executing down on tang" "$COMP_OUT_PATH"' \
+ "Expected info message at beginning of execution"
+CHECK $'[ $COMP_EXIT_CODE -eq 0 ]' \
+ "Expected EXIT_CODE = 0"
+
+SETUP "cleaning, but deny deleting data" \
"clean tang" \
"n"
+CHECK $'grep -sq "Executing clean on tang" "$COMP_OUT_PATH"' \
+ "Expected info message at beginning of execution"
CHECK $'[ $COMP_EXIT_CODE -eq 0 ]' \
"Expected EXIT_CODE = 0"
CHECK $'grep -sq "Remove \'tang/data\' (y/N)?" "$COMP_OUT_PATH"' \
"Expected confirmation prompt before deletion"
-CHECK $'[ -f tang/.env ]' \
+CHECK $'[ -d tang/data ]' \
"Expected data is not deleted"
-SETUP "allow deleting data" \
+SETUP "cleaning, and allow deleting data" \
"clean tang" \
"y"
+CHECK $'grep -sq "Executing clean on tang" "$COMP_OUT_PATH"' \
+ "Expected info message at beginning of execution"
CHECK $'[ $COMP_EXIT_CODE -eq 0 ]' \
"Expected EXIT_CODE = 0"
CHECK $'grep -sq "Remove \'tang/data\' (y/N)?" "$COMP_OUT_PATH"' \
"Expected confirmation prompt before deletion"
-CHECK $'! [ -f tang/.env ]' \
+CHECK $'! [ -d tang/data ]' \
"Expected data is deleted"
exit "$FINAL_EXIT_CODE"
diff --git a/comp b/comp
index 64a12e8..0440b05 100755
--- a/comp
+++ b/comp
@@ -138,6 +138,15 @@ __gen_templates () {
done < <(find ./extra -name '*.template.*')
}
+__grab_ps () {
+ # FIXME: `podman` doesn't print health status!
+ local _ps_res="$( $DOCKER_CMD ps \
+ --format '{{.Label "com.docker.compose.service"}}\t{{.Status}}' \
+ --filter label=com.docker.compose.project=$comp \
+ )"
+ eval "$1"='$_ps_res'
+}
+
__maybe_fail_fast () {
[ "$FLAG_FAIL_FAST" != "yes" ] || exit "$1"
@@ -216,20 +225,25 @@ __verify_volumes () {
}
__will_invoke_compose () {
- [ "$1" = "down" ] || [ "$1" = "pull" ] || [ "$1" = "status" ] || [ "$1" = "up" ]
+ [ "$1" = "down" ] || [ "$1" = "pull" ] || [ "$1" = "up" ]
}
# # # # # # # # # # # # # # # # # # # TOP-LEVEL VERBS # # # # # # # # # # # # # # # # # # #
do_validate () {
- [ "$1" = "shallow" ] || __do_prereqs validate || return 1
+ [ "${1:-}" = "shallow" ] || __do_prereqs validate || return 1
+
+ if echo "$comp" | grep -q '\.'; then
+ __error "$DOCKER_COMPOSE_CMD will use '${comp//.}' as project name."
+ return 1
+ fi
printf '[~] Validating service:'
for svc in $("$YQ_CMD" -M '.services | keys | .[]' docker-compose.yml) ; do
local attrs=( $("$YQ_CMD" -M ".services.\"$svc\" | keys | .[]" docker-compose.yml) )
echo -n " $svc"
for bad_attr in devices labels logging ports ; do
- if printf '%s\0' "${attrs[@]}" | grep -Fxqz -- $bad_attr; then
+ if printf '%s\0' "${attrs[@]}" | grep -Fxqz -- $bad_attr ; then
echo ; __error "'$bad_attr' for '$svc' should be in docker_compose.$bad_attr.yml."
return 1
fi
@@ -239,12 +253,18 @@ do_validate () {
}
do_clean () {
- do_down || return 1
-
- echo -n "Remove '$comp/data' (y/N)? " ; read -rn1 2>&1 ; echo
- [[ $REPLY =~ ^[Yy]$ ]] || return 0
+ __grab_ps __ps_before_clean
+ if [ -n "$__ps_before_clean" ] ; then
+ __error "Cannot clean while ${_bold_}$comp${_normal_} is running!"
+ return 1
+ fi
- rm -rfv data generated .env
+ rm -rfv generated .env
+ if [ -d data ] ; then
+ echo -n "Remove '$comp/data' (y/N)? " ; read -rn1 2>&1
+ [[ $REPLY =~ ^[Yy]$ ]] && echo || return 0
+ fi
+ rm -rfv data
}
do_down () {
@@ -277,11 +297,12 @@ do_pull () {
do_status () {
__do_prereqs status || return 1
+ __grab_ps __ps_before_status
printf '[?] Querying service:'
for svc in $( "$YQ_CMD" -M '.services | keys | .[]' docker-compose.yml ) ; do
echo -n " $svc"
- if ! ( $DOCKER_COMPOSE_CMD ps "$svc" 2> /dev/null | grep -q healthy ) ; then
- echo ; __error "'$svc' is not healthy."
+ if ! ( echo "$__ps_before_status" | grep "$svc" | grep -q healthy ) ; then
+ echo ; __error "Unhealthy service: ${_fg_red_}$svc${_normal_}"
return 1
fi
done
@@ -303,14 +324,14 @@ usage () {
Usage:
$0 [,,...] [flags] [ ...]
-Verbs: (short forms within [])
- [c]lean Delete '/data'
- [d]own Stop a composition
- [o]verrides List all override files in a composition
- [p]ull Pull all images for a composition
- [s]tatus Display health / status of a composition
- [u]p Start a composition
- [v]alidate Validate a composition
+Verbs: (short forms within <>)
+ lean Delete '/data'
+ own Stop a composition
+ verrides List all override files in a composition
+ ull Pull all images for a composition
+ tatus Display health / status of a composition
+ p Start a composition
+ alidate Validate a composition
Flags:
[-P | --skip-prereqs] Ignore verifying/starting prerequisite compositions
@@ -475,15 +496,15 @@ perform () {
local SIMPLE_VERB="$1"
for comp in "${COMPOSITIONS[@]}" ; do
comp="${comp%/}"
- echo -ne "\n${_fg_white_}${_bg_black_}${_bold_}[${SIMPLE_VERB:0:1}]${_normal_} Executing ${_bold_}$SIMPLE_VERB${_normal_} on "
+ echo -ne "\n${_fg_white_}${_bg_black_}${_bold_} ${SIMPLE_VERB:0:1} ${_normal_} Executing ${_bold_}$SIMPLE_VERB${_normal_} on "
[ -z "$COMP_INTERNAL_CALL" ] || printf 'pre-req '
echo "${_bold_}$comp${_normal_} ... "
if ! { [ "$comp" = "$(basename "$comp")" ] && [ -d "$SELF_DIR/$comp" ]; } ; then
- __error "'$comp' is not a base directory at '$SELF_DIR'!"
+ __error "${_bold_}$comp${_normal_} is not a base directory at '$SELF_DIR'!"
__maybe_fail_fast $EXIT_CODE_COMPOSITION_NOT_FOUND || continue
fi
if ! [ -f "$SELF_DIR/$comp/docker-compose.yml" ] ; then
- __error "No 'docker-compose.yml' found under '$comp'!"
+ __error "No 'docker-compose.yml' found under ${_bold_}$comp${_normal_}!"
__maybe_fail_fast $EXIT_CODE_COMPOSITION_NOT_FOUND || continue
fi
@@ -526,8 +547,8 @@ perform () {
local verb_exit=0
"do_${SIMPLE_VERB}" ; verb_exit=$?
- [ "$SIMPLE_VERB" != "validate" ] || [ $verb_exit -ne 0 ] || echo "[=] '$comp' is valid!"
- [ "$SIMPLE_VERB" != "status" ] || [ $verb_exit -ne 0 ] || echo "[=] '$comp' is healthy!"
+ [ "$SIMPLE_VERB" != "validate" ] || [ $verb_exit -ne 0 ] || echo "[=] ${_bold_}$comp${_normal_} is valid!"
+ [ "$SIMPLE_VERB" != "status" ] || [ $verb_exit -ne 0 ] || echo "[=] ${_bold_}$comp${_normal_} is healthy!"
[ $verb_exit -eq 0 ] \
|| __maybe_fail_fast $EXIT_CODE_SIMPLE_VERB_FAILURE || continue
diff --git a/docker.sock/docker-compose.labels.yml b/docker_sock/docker-compose.labels.yml
similarity index 97%
rename from docker.sock/docker-compose.labels.yml
rename to docker_sock/docker-compose.labels.yml
index 70ca852..4ca57e7 100644
--- a/docker.sock/docker-compose.labels.yml
+++ b/docker_sock/docker-compose.labels.yml
@@ -5,6 +5,6 @@ services:
labels:
traefik.enable: true
traefik.docker.network: shared
- traefik.http.routers.docker_sock.rule: PathPrefix(`/docker.sock`)
+ traefik.http.routers.docker_sock.rule: PathPrefix(`/docker_sock`)
traefik.http.services.docker_sock.loadBalancer.server.port: 9000
traefik.http.routers.docker_sock.entryPoints: lan-https
diff --git a/docker.sock/docker-compose.logging.yml b/docker_sock/docker-compose.logging.yml
similarity index 100%
rename from docker.sock/docker-compose.logging.yml
rename to docker_sock/docker-compose.logging.yml
diff --git a/docker.sock/docker-compose.yml b/docker_sock/docker-compose.yml
similarity index 100%
rename from docker.sock/docker-compose.yml
rename to docker_sock/docker-compose.yml
diff --git a/kodi.db/config/mariadb/docker-entrypoint-initdb.d/kodi.sql b/kodi_db/config/mariadb/docker-entrypoint-initdb.d/kodi.sql
similarity index 100%
rename from kodi.db/config/mariadb/docker-entrypoint-initdb.d/kodi.sql
rename to kodi_db/config/mariadb/docker-entrypoint-initdb.d/kodi.sql
diff --git a/kodi.db/docker-compose.logging.yml b/kodi_db/docker-compose.logging.yml
similarity index 100%
rename from kodi.db/docker-compose.logging.yml
rename to kodi_db/docker-compose.logging.yml
diff --git a/kodi.db/docker-compose.ports.yml b/kodi_db/docker-compose.ports.yml
similarity index 100%
rename from kodi.db/docker-compose.ports.yml
rename to kodi_db/docker-compose.ports.yml
diff --git a/kodi.db/docker-compose.pre_hook.sh b/kodi_db/docker-compose.pre_hook.sh
similarity index 100%
rename from kodi.db/docker-compose.pre_hook.sh
rename to kodi_db/docker-compose.pre_hook.sh
diff --git a/kodi.db/docker-compose.yml b/kodi_db/docker-compose.yml
similarity index 90%
rename from kodi.db/docker-compose.yml
rename to kodi_db/docker-compose.yml
index bef6e3d..3e37edd 100644
--- a/kodi.db/docker-compose.yml
+++ b/kodi_db/docker-compose.yml
@@ -16,7 +16,7 @@ services:
- ./data/mariadb/var/lib/mysql:/var/lib/mysql
environment:
- MARIADB_ROOT_PASSWORD: 'kodi.db_mariadb_root_password'
+ MARIADB_ROOT_PASSWORD: 'kodi_db_mariadb_root_password'
healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
diff --git a/telegraf/pre.reqs b/telegraf/pre.reqs
index 91745f5..180d4a7 100644
--- a/telegraf/pre.reqs
+++ b/telegraf/pre.reqs
@@ -1 +1 @@
-docker.sock
+docker_sock
diff --git a/traefik/pre.reqs b/traefik/pre.reqs
index 91745f5..180d4a7 100644
--- a/traefik/pre.reqs
+++ b/traefik/pre.reqs
@@ -1 +1 @@
-docker.sock
+docker_sock
|