132 lines
3.8 KiB
Bash
Executable File
132 lines
3.8 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Validate operator-managed Compose inputs before delegating to Docker Compose.
|
|
set -euo pipefail
|
|
|
|
usage() {
|
|
echo "usage: $0 --env-file <operator.env> -f <compose.yaml> ... <docker-compose-command>" >&2
|
|
exit 2
|
|
}
|
|
|
|
trim() {
|
|
local value="$1"
|
|
value="${value#"${value%%[![:space:]]*}"}"
|
|
value="${value%"${value##*[![:space:]]}"}"
|
|
printf '%s' "$value"
|
|
}
|
|
|
|
is_safe_absolute_path() {
|
|
local value="$1" segment
|
|
local -a segments
|
|
[[ "$value" == /* && "$value" != *//* ]] || return 1
|
|
IFS=/ read -r -a segments <<<"$value"
|
|
for segment in "${segments[@]}"; do
|
|
[[ "$segment" != . && "$segment" != .. ]] || return 1
|
|
done
|
|
}
|
|
|
|
read_env_value() {
|
|
local source="$1" wanted="$2" line trimmed name value result=""
|
|
while IFS= read -r line || [[ -n "$line" ]]; do
|
|
trimmed="$(trim "$line")"
|
|
[[ -n "$trimmed" && "$trimmed" != \#* && "$trimmed" == *=* ]] || continue
|
|
name="$(trim "${trimmed%%=*}")"
|
|
[[ "$name" == "$wanted" ]] || continue
|
|
value="$(trim "${trimmed#*=}")"
|
|
value="$(trim "${value%%#*}")"
|
|
value="${value#\"}"; value="${value%\"}"
|
|
value="${value#\'}"; value="${value%\'}"
|
|
result="$value"
|
|
done <"$source"
|
|
printf '%s' "$result"
|
|
}
|
|
|
|
source_names() {
|
|
local source="$1" line trimmed name
|
|
{
|
|
while IFS= read -r line || [[ -n "$line" ]]; do
|
|
trimmed="$(trim "$line")"
|
|
[[ -n "$trimmed" && "$trimmed" != \#* && "$trimmed" == *=* ]] || continue
|
|
name="$(trim "${trimmed%%=*}")"
|
|
[[ "$name" =~ ^[A-Za-z_][A-Za-z0-9_]*_SOURCE$ ]] && printf '%s\n' "$name"
|
|
done <"$source"
|
|
while IFS= read -r line; do
|
|
name="${line%%=*}"
|
|
[[ "$name" =~ ^[A-Za-z_][A-Za-z0-9_]*_SOURCE$ ]] && printf '%s\n' "$name"
|
|
done < <(env)
|
|
} | sort -u
|
|
}
|
|
|
|
record_git_transport() {
|
|
local compose_file="$1" transport=""
|
|
[[ -f "$compose_file" ]] || return 0
|
|
transport="$(awk '
|
|
/^[[:space:]]*x-thoth-git-transport:[[:space:]]*/ {
|
|
value = $0
|
|
sub(/^[[:space:]]*x-thoth-git-transport:[[:space:]]*/, "", value)
|
|
sub(/[[:space:]]*#.*/, "", value)
|
|
print value
|
|
exit
|
|
}
|
|
' "$compose_file")"
|
|
case "$transport" in
|
|
ssh) ssh_override=1 ;;
|
|
https) https_override=1 ;;
|
|
"")
|
|
case "$(basename "$compose_file")" in
|
|
*git-ssh*.yaml|*git-ssh*.yml) ssh_override=1 ;;
|
|
*git-https*.yaml|*git-https*.yml) https_override=1 ;;
|
|
esac
|
|
;;
|
|
*) echo "invalid x-thoth-git-transport in $compose_file" >&2; exit 2 ;;
|
|
esac
|
|
}
|
|
|
|
env_file=""
|
|
ssh_override=0
|
|
https_override=0
|
|
arguments=("$@")
|
|
for ((index = 0; index < ${#arguments[@]}; index += 1)); do
|
|
argument="${arguments[index]}"
|
|
case "$argument" in
|
|
--env-file)
|
|
((index + 1 < ${#arguments[@]})) || usage
|
|
((index += 1))
|
|
env_file="${arguments[index]}"
|
|
;;
|
|
--env-file=*) env_file="${argument#--env-file=}" ;;
|
|
-f|--file)
|
|
((index + 1 < ${#arguments[@]})) || usage
|
|
((index += 1))
|
|
compose_file="${arguments[index]}"
|
|
record_git_transport "$compose_file"
|
|
;;
|
|
--file=*)
|
|
compose_file="${argument#--file=}"
|
|
record_git_transport "$compose_file"
|
|
;;
|
|
esac
|
|
done
|
|
|
|
[[ -n "$env_file" && -f "$env_file" ]] || { echo "Compose preflight requires an existing --env-file" >&2; exit 2; }
|
|
if ((ssh_override && https_override)); then
|
|
echo "SSH and HTTPS Git overrides are mutually exclusive" >&2
|
|
exit 2
|
|
fi
|
|
|
|
while IFS= read -r name; do
|
|
if [[ "$name" == *"_VECTOR_"* || "$name" == *"_EMBEDDING_"* || "$name" == THT_VECTOR_* ]]; then
|
|
echo "retired semantic source path is not supported: $name" >&2
|
|
exit 2
|
|
fi
|
|
value="$(read_env_value "$env_file" "$name")"
|
|
if [[ -v "$name" ]]; then
|
|
value="${!name}"
|
|
fi
|
|
if [[ -n "$value" ]] && ! is_safe_absolute_path "$value"; then
|
|
echo "unsafe source path for $name in $env_file" >&2
|
|
exit 2
|
|
fi
|
|
done < <(source_names "$env_file")
|
|
|
|
exec docker compose "${arguments[@]}"
|