Files
kestra-scripts/docker_stack_inventory_scan.yaml
T
2026-06-26 17:24:14 +02:00

224 lines
7.0 KiB
YAML

id: docker_stack_inventory_scan
namespace: homelab.docker
description: Scannt Docker-Compose-Stacks auf mehreren Remote-Docker-Hosts per SSH und schreibt eine Dropdown-Liste in den KV-Store. Das Python-Script wird aus dem Git-Repo geladen.
variables:
ssh_user: meinuser
base_dir: /home/meinuser/docker
kv_select_options_key: docker_stack_select_options
git_repo_url: https://git.unixweb.net/joachim/kestra-scripts.git
git_branch: main
python_script_name: build_select_options.py
docker_hosts:
- docker1;192.168.100.10
- docker2;192.168.100.11
- docker3;192.168.100.12
- docker4;192.168.100.13
- docker5;192.168.100.14
- nextcloud;192.168.100.15
triggers:
- id: every_30_minutes
type: io.kestra.plugin.core.trigger.Schedule
cron: "*/30 * * * *"
disabled: false
tasks:
- id: scan_all_docker_hosts
type: io.kestra.plugin.core.flow.ForEach
values: "{{ vars.docker_hosts }}"
tasks:
- id: scan_remote_docker_host
type: io.kestra.plugin.fs.ssh.Command
host: "{{ taskrun.value | split(';') | slice(1, 2) | first }}"
port: "22"
authMethod: PUBLIC_KEY
username: "{{ vars.ssh_user }}"
privateKey: "{{ secret('SSH_PRIVATE_KEY') }}"
strictHostKeyChecking: "no"
commands:
- |
set +e
HOST_ENTRY="{{ taskrun.value }}"
BASE_DIR="{{ vars.base_dir }}"
SSH_USER="{{ vars.ssh_user }}"
HOST_NAME="$(printf '%s' "$HOST_ENTRY" | cut -d';' -f1)"
HOST_IP="$(printf '%s' "$HOST_ENTRY" | cut -d';' -f2)"
json_escape() {
printf '%s' "$1" | sed 's/\\/\\\\/g; s/"/\\"/g'
}
to_b64() {
printf '%s' "$1" | base64 | tr -d '\n'
}
echo "=========================================="
echo "Docker Stack Inventory Scan gestartet"
echo "=========================================="
echo "Host-Name: $HOST_NAME"
echo "Host-IP: $HOST_IP"
echo "SSH-Benutzer: $SSH_USER"
echo "Basisverzeichnis: $BASE_DIR"
echo "Zeitpunkt: $(date '+%Y-%m-%d %H:%M:%S')"
echo "=========================================="
OPTIONS_JSON="[]"
if [ ! -d "$BASE_DIR" ]; then
echo "WARNUNG: Basisverzeichnis existiert nicht: $BASE_DIR"
else
OPTIONS_JSON="["
OPTION_SEP=""
COMPOSE_FILES="$(find "$BASE_DIR" -maxdepth 2 -type f \( \
-name compose.yml -o \
-name compose.yaml -o \
-name docker-compose.yml -o \
-name docker-compose.yaml \
\) | sort)"
if [ -n "$COMPOSE_FILES" ]; then
while IFS= read -r COMPOSE_PATH; do
[ -z "$COMPOSE_PATH" ] && continue
COMPOSE_DIR="$(dirname "$COMPOSE_PATH")"
STACK_NAME="$(basename "$COMPOSE_DIR")"
echo "Stack gefunden: $STACK_NAME -> $COMPOSE_DIR"
OPTION_VALUE="${HOST_NAME};${HOST_IP};${SSH_USER};${COMPOSE_DIR}"
ESC_OPTION_VALUE="$(json_escape "$OPTION_VALUE")"
OPTIONS_JSON="${OPTIONS_JSON}${OPTION_SEP}\"${ESC_OPTION_VALUE}\""
OPTION_SEP=","
done <<EOF
$COMPOSE_FILES
EOF
fi
OPTIONS_JSON="${OPTIONS_JSON}]"
fi
STACK_COUNT="$(printf '%s' "$OPTIONS_JSON" | grep -o "$HOST_NAME;$HOST_IP" | wc -l | tr -d ' ')"
echo "=========================================="
echo "Inventory Scan Host abgeschlossen"
echo "Host: $HOST_NAME / $HOST_IP"
echo "Stacks gefunden: $STACK_COUNT"
echo "=========================================="
OPTIONS_JSON_B64="$(to_b64 "$OPTIONS_JSON")"
printf '::{"outputs":{"select_options_b64":"%s"}}::\n' "$OPTIONS_JSON_B64"
exit 0
- id: build_select_options_workspace
type: io.kestra.plugin.core.flow.WorkingDirectory
tasks:
- id: clone_kestra_scripts_repo
type: io.kestra.plugin.git.Clone
url: "{{ vars.git_repo_url }}"
branch: "{{ vars.git_branch }}"
- id: build_select_options_json
type: io.kestra.plugin.scripts.shell.Commands
taskRunner:
type: io.kestra.plugin.core.runner.Process
outputFiles:
- select_options.json
env:
OPTIONS_B64_JSON: |
[
{% for host_entry in vars.docker_hosts %}
"{{ outputs.scan_remote_docker_host[host_entry].vars.select_options_b64 }}"{% if not loop.last %},{% endif %}
{% endfor %}
]
commands:
- |
set -e
echo "=========================================="
echo "Geklontes Git-Repo"
echo "=========================================="
echo "Repo: {{ vars.git_repo_url }}"
echo "Branch: {{ vars.git_branch }}"
echo ""
echo "Dateien im Repo:"
find . -maxdepth 4 -type f | sort
echo ""
echo "=========================================="
echo "Python-Script suchen"
echo "=========================================="
SCRIPT_PATH="$(find . -type f -name '{{ vars.python_script_name }}' | sort | head -n 1)"
if [ -z "$SCRIPT_PATH" ]; then
echo "FEHLER: Python-Script wurde nicht gefunden: {{ vars.python_script_name }}"
echo ""
echo "Gefundene Python-Dateien:"
find . -type f -name '*.py' | sort || true
exit 1
fi
echo "Gefundenes Script: $SCRIPT_PATH"
echo ""
echo "=========================================="
echo "Python-Script ausführen"
echo "=========================================="
python3 "$SCRIPT_PATH"
echo ""
echo "=========================================="
echo "Erzeugte Dropdown-Datei"
echo "=========================================="
if [ ! -f select_options.json ]; then
echo "FEHLER: select_options.json wurde nicht erzeugt"
exit 1
fi
cat select_options.json
- id: write_select_options_to_kv_store
type: io.kestra.plugin.core.kv.Set
key: "{{ vars.kv_select_options_key }}"
kvType: JSON
overwrite: true
value: "{{ read(outputs.build_select_options_json.outputFiles['select_options.json']) }}"
- id: final_log
type: io.kestra.plugin.core.log.Log
message: |
Multi-Host Docker Stack Dropdown wurde in den KV-Store geschrieben.
KV-Key:
{{ vars.kv_select_options_key }}
Git-Repo:
{{ vars.git_repo_url }}
Branch:
{{ vars.git_branch }}
Gesuchtes Python-Script:
{{ vars.python_script_name }}
Basisverzeichnis:
{{ vars.base_dir }}
SSH-Benutzer:
{{ vars.ssh_user }}