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 <