#!/usr/bin/env bash set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SEARCH_DIR="$SCRIPT_DIR" CONFIG_PATH="" while true; do CANDIDATE="$SEARCH_DIR/.clawdbot/credentials/portainer/config.json" if [[ -f "$CANDIDATE" ]]; then CONFIG_PATH="$CANDIDATE" break fi PARENT="$(dirname "$SEARCH_DIR")" if [[ "$PARENT" == "$SEARCH_DIR" ]]; then break fi SEARCH_DIR="$PARENT" done if [[ -z "$CONFIG_PATH" && -f "$HOME/.clawdbot/credentials/portainer/config.json" ]]; then CONFIG_PATH="$HOME/.clawdbot/credentials/portainer/config.json" fi err() { echo "Error: $*" >&2 exit 1 } require_cmd() { command -v "$1" >/dev/null 2>&1 || err "Required command not found: $1" } require_cmd curl require_cmd jq [[ -f "$CONFIG_PATH" ]] || err "Missing config file: $CONFIG_PATH" BASE_URL="$(jq -r '.base_url // empty' "$CONFIG_PATH")" API_KEY="$(jq -r '.api_key // empty' "$CONFIG_PATH")" [[ -n "$BASE_URL" ]] || err "config.base_url is missing" [[ -n "$API_KEY" ]] || err "config.api_key is missing" BASE_URL="${BASE_URL%/}" response="$(curl -sS -w $'\n%{http_code}' \ -H "X-API-Key: $API_KEY" \ "$BASE_URL/api/stacks")" http_code="$(printf '%s' "$response" | tail -n1)" body="$(printf '%s' "$response" | sed '$d')" if [[ "$http_code" -lt 200 || "$http_code" -ge 300 ]]; then msg="$(printf '%s' "$body" | jq -r '.message // empty' 2>/dev/null || true)" [[ -n "$msg" ]] || msg="$body" err "Portainer API request failed (HTTP $http_code): $msg" fi printf '%s' "$body" | jq -r '.[] | "\(.Id)\t\(.Name)\t\(.Status)"'