224 lines
7.0 KiB
YAML
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 }}
|