a1a17e81a1
Includes updated JS challenge scripts with Claude-User whitelist, same-site referer bypass, Blackbox-Exporter allowed bot, and all new exporters, cheat sheets, and automation scripts.
609 lines
23 KiB
Bash
Executable File
609 lines
23 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
#########################################################################################
|
|
#### contabo-fleet-manager.sh — Inventory, health checks, and bulk operations for ####
|
|
#### Contabo VPS/VDS instances via the REST API. Fleet-wide visibility and control ####
|
|
#### Requires: bash 4+, curl, jq ####
|
|
#### ####
|
|
#### Author: Phil Connor ####
|
|
#### Contact: contact@mylinux.work ####
|
|
#### License: MIT ####
|
|
#### Version 1.01 ####
|
|
#### ####
|
|
#### Usage: ####
|
|
#### ./contabo-fleet-manager.sh --inventory --all ####
|
|
#### ####
|
|
#### See --help for all options. ####
|
|
#########################################################################################
|
|
|
|
set -euo pipefail
|
|
|
|
# ── Colors (pre-initialized) ─────────────────────────────────────────
|
|
RED="" GREEN="" YELLOW="" BLUE="" CYAN="" BOLD="" DIM="" RESET=""
|
|
|
|
setup_colors() {
|
|
if [[ "${COLOR:-auto}" == "never" ]]; then
|
|
return
|
|
fi
|
|
if [[ "${COLOR:-auto}" == "always" ]] || [[ -t 1 ]]; then
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[0;33m'
|
|
BLUE='\033[0;34m'
|
|
CYAN='\033[0;36m'
|
|
BOLD='\033[1m'
|
|
DIM='\033[2m'
|
|
RESET='\033[0m'
|
|
fi
|
|
}
|
|
|
|
# ── Logging ───────────────────────────────────────────────────────────
|
|
log() { echo -e "${BLUE}[INFO]${RESET} $*"; }
|
|
warn() { echo -e "${YELLOW}[WARN]${RESET} $*" >&2; }
|
|
err() { echo -e "${RED}[ERROR]${RESET} $*" >&2; }
|
|
verbose() { if [[ "$VERBOSE" == "true" ]]; then echo -e "${DIM}[DEBUG]${RESET} $*"; fi; }
|
|
die() { err "$*"; exit 1; }
|
|
|
|
section_header() {
|
|
echo ""
|
|
echo -e " ${BOLD}${CYAN}── $1 ──${RESET}"
|
|
echo ""
|
|
}
|
|
|
|
field() {
|
|
printf " ${BOLD}%-22s${RESET} %s\n" "$1" "$2"
|
|
}
|
|
|
|
field_color() {
|
|
printf " ${BOLD}%-22s${RESET} %b\n" "$1" "$2"
|
|
}
|
|
|
|
elapsed() {
|
|
local end_time
|
|
end_time=$(date +%s)
|
|
echo "$(( end_time - START_TIME ))s"
|
|
}
|
|
|
|
# ── Defaults ──────────────────────────────────────────────────────────
|
|
RUN_MODE=""
|
|
INSTANCE_ID=""
|
|
TARGET_ALL="false"
|
|
TAG_ID=""
|
|
TAG_SUB_MODE=""
|
|
OUTPUT_FORMAT="${CFM_FORMAT:-text}"
|
|
PING_CHECK="false"
|
|
FORCE="false"
|
|
VERBOSE="${VERBOSE:-false}"
|
|
COLOR="${COLOR:-auto}"
|
|
|
|
# ── Credentials ───────────────────────────────────────────────────────
|
|
CONTABO_CLIENT_ID="${CONTABO_CLIENT_ID:-}"
|
|
CONTABO_CLIENT_SECRET="${CONTABO_CLIENT_SECRET:-}"
|
|
CONTABO_API_USER="${CONTABO_API_USER:-}"
|
|
CONTABO_API_PASS="${CONTABO_API_PASS:-}"
|
|
|
|
# ── State ─────────────────────────────────────────────────────────────
|
|
SCRIPT_NAME="$(basename "$0")"
|
|
readonly SCRIPT_NAME
|
|
START_TIME=""
|
|
ACTION_OK=0
|
|
ACTION_FAIL=0
|
|
|
|
# ── API helpers ──────────────────────────────────────────────────────
|
|
contabo_token() {
|
|
local resp
|
|
resp=$(curl -s -d "client_id=${CONTABO_CLIENT_ID}" \
|
|
-d "client_secret=${CONTABO_CLIENT_SECRET}" \
|
|
--data-urlencode "username=${CONTABO_API_USER}" \
|
|
--data-urlencode "password=${CONTABO_API_PASS}" \
|
|
-d "grant_type=password" \
|
|
"https://auth.contabo.com/auth/realms/contabo/protocol/openid-connect/token")
|
|
local token
|
|
token=$(echo "$resp" | jq -r '.access_token // empty' 2>/dev/null)
|
|
if [[ -z "$token" ]]; then
|
|
die "Failed to obtain access token — check credentials"
|
|
fi
|
|
echo "$token"
|
|
}
|
|
|
|
contabo_api() {
|
|
local method="$1" endpoint="$2"
|
|
shift 2
|
|
local attempt=0 max_attempts=3
|
|
|
|
while (( attempt < max_attempts )); do
|
|
local http_code
|
|
http_code=$(curl -s -o /tmp/cfm_resp.json -w "%{http_code}" \
|
|
-X "$method" \
|
|
-H "Authorization: Bearer $(contabo_token)" \
|
|
-H "Content-Type: application/json" \
|
|
-H "x-request-id: $(cat /proc/sys/kernel/random/uuid 2>/dev/null || date +%s%N)" \
|
|
"https://api.contabo.com/v1${endpoint}" "$@")
|
|
|
|
verbose "API ${method} ${endpoint} → HTTP ${http_code}"
|
|
|
|
if [[ "$http_code" == "429" ]]; then
|
|
((attempt++)) || true
|
|
local wait=$(( attempt * 5 ))
|
|
warn "Rate limited — retrying in ${wait}s (attempt ${attempt}/${max_attempts})"
|
|
sleep "$wait"
|
|
continue
|
|
fi
|
|
|
|
cat /tmp/cfm_resp.json
|
|
return 0
|
|
done
|
|
|
|
err "API request failed after ${max_attempts} attempts: ${method} ${endpoint}"
|
|
return 1
|
|
}
|
|
|
|
check_credentials() {
|
|
[[ -z "$CONTABO_CLIENT_ID" ]] && die "CONTABO_CLIENT_ID not set"
|
|
[[ -z "$CONTABO_CLIENT_SECRET" ]] && die "CONTABO_CLIENT_SECRET not set"
|
|
[[ -z "$CONTABO_API_USER" ]] && die "CONTABO_API_USER not set"
|
|
[[ -z "$CONTABO_API_PASS" ]] && die "CONTABO_API_PASS not set"
|
|
}
|
|
|
|
check_deps() {
|
|
command -v curl &>/dev/null || die "curl is required"
|
|
command -v jq &>/dev/null || die "jq is required"
|
|
}
|
|
|
|
# ── Instance helpers ─────────────────────────────────────────────────
|
|
get_all_instance_ids() {
|
|
local page=1 size=100 ids=""
|
|
while true; do
|
|
local resp
|
|
resp=$(contabo_api GET "/compute/instances?page=${page}&size=${size}")
|
|
local page_ids
|
|
page_ids=$(echo "$resp" | jq -r '.data[].instanceId' 2>/dev/null)
|
|
[[ -z "$page_ids" ]] && break
|
|
ids="${ids}${ids:+$'\n'}${page_ids}"
|
|
local count
|
|
count=$(echo "$page_ids" | wc -l)
|
|
(( count < size )) && break
|
|
((page++)) || true
|
|
done
|
|
echo "$ids"
|
|
}
|
|
|
|
get_instance_name() {
|
|
local iid="$1"
|
|
contabo_api GET "/compute/instances/${iid}" \
|
|
| jq -r '.data[0].name // .data[0].displayName // "unknown"' 2>/dev/null
|
|
}
|
|
|
|
get_instance_ids() {
|
|
if [[ "$TARGET_ALL" == "true" ]]; then
|
|
get_all_instance_ids
|
|
elif [[ -n "$INSTANCE_ID" ]]; then
|
|
echo "$INSTANCE_ID"
|
|
elif [[ -n "$TAG_ID" ]]; then
|
|
get_instances_by_tag "$TAG_ID"
|
|
else
|
|
die "Specify --instance ID, --all, or --tag TAG_ID"
|
|
fi
|
|
}
|
|
|
|
get_instances_by_tag() {
|
|
local tid="$1"
|
|
local page=1 size=100 ids=""
|
|
while true; do
|
|
local resp
|
|
resp=$(contabo_api GET "/compute/instances?page=${page}&size=${size}")
|
|
local page_ids
|
|
page_ids=$(echo "$resp" | jq -r --arg tid "$tid" \
|
|
'.data[] | select(.tags[]? | .tagId == ($tid | tonumber)) | .instanceId' 2>/dev/null)
|
|
[[ -z "$page_ids" ]] && break
|
|
ids="${ids}${ids:+$'\n'}${page_ids}"
|
|
local count
|
|
count=$(echo "$page_ids" | wc -l)
|
|
(( count < size )) && break
|
|
((page++)) || true
|
|
done
|
|
echo "$ids"
|
|
}
|
|
|
|
# ══════════════════════════════════════════════════════════════════════
|
|
# INVENTORY
|
|
# ══════════════════════════════════════════════════════════════════════
|
|
do_inventory() {
|
|
local page=1 size=100 all_data="[]"
|
|
|
|
while true; do
|
|
local resp
|
|
resp=$(contabo_api GET "/compute/instances?page=${page}&size=${size}")
|
|
local page_data
|
|
page_data=$(echo "$resp" | jq '.data // []' 2>/dev/null)
|
|
local page_count
|
|
page_count=$(echo "$page_data" | jq 'length' 2>/dev/null || echo 0)
|
|
[[ "$page_count" -eq 0 ]] && break
|
|
all_data=$(echo -e "${all_data}\n${page_data}" | jq -s 'add' 2>/dev/null)
|
|
(( page_count < size )) && break
|
|
((page++)) || true
|
|
done
|
|
|
|
local total
|
|
total=$(echo "$all_data" | jq 'length' 2>/dev/null || echo 0)
|
|
[[ "$total" -eq 0 ]] && die "No instances found"
|
|
|
|
# Filter by tag if specified
|
|
if [[ -n "$TAG_ID" ]]; then
|
|
all_data=$(echo "$all_data" | jq --arg tid "$TAG_ID" \
|
|
'[.[] | select(.tags[]? | .tagId == ($tid | tonumber))]' 2>/dev/null)
|
|
total=$(echo "$all_data" | jq 'length' 2>/dev/null || echo 0)
|
|
[[ "$total" -eq 0 ]] && die "No instances found with tag ${TAG_ID}"
|
|
fi
|
|
|
|
case "$OUTPUT_FORMAT" in
|
|
json)
|
|
echo "$all_data" | jq '.'
|
|
;;
|
|
ansible)
|
|
echo "[contabo]"
|
|
echo "$all_data" | jq -r \
|
|
'.[] | (.ipConfig.v4.ip // "unknown") + " # " + (.name // .displayName // "unknown") + " id=" + (.instanceId | tostring)' \
|
|
2>/dev/null
|
|
;;
|
|
*)
|
|
section_header "Fleet Inventory"
|
|
|
|
printf " ${BOLD}%-13s %-20s %-11s %-16s %-8s %-8s${RESET}\n" \
|
|
"INSTANCE_ID" "NAME" "STATUS" "IP" "REGION" "PRODUCT"
|
|
printf " %s\n" "$(printf '%.0s─' {1..78})"
|
|
|
|
echo "$all_data" | jq -r \
|
|
'.[] | "\(.instanceId)\t\(.name // .displayName // "unknown")\t\(.status // "unknown")\t\(.ipConfig.v4.ip // "—")\t\(.region // "—")\t\(.productId // "—")"' \
|
|
2>/dev/null \
|
|
| while IFS=$'\t' read -r iid name status ip region product; do
|
|
printf " %-13s %-20s %-11s %-16s %-8s %-8s\n" \
|
|
"$iid" "${name:0:18}" "$status" "$ip" "${region:0:6}" "$product"
|
|
done
|
|
|
|
echo ""
|
|
field "Total:" "$total"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# ══════════════════════════════════════════════════════════════════════
|
|
# HEALTH
|
|
# ══════════════════════════════════════════════════════════════════════
|
|
do_health() {
|
|
local ids
|
|
ids=$(get_instance_ids)
|
|
[[ -z "$ids" ]] && die "No instances found"
|
|
|
|
local running=0 stopped=0 errored=0 total_instances=0
|
|
local results=""
|
|
|
|
while IFS= read -r iid; do
|
|
[[ -z "$iid" ]] && continue
|
|
((total_instances++)) || true
|
|
|
|
local resp
|
|
resp=$(contabo_api GET "/compute/instances/${iid}")
|
|
local name status ip
|
|
name=$(echo "$resp" | jq -r '.data[0].name // .data[0].displayName // "unknown"' 2>/dev/null)
|
|
status=$(echo "$resp" | jq -r '.data[0].status // "unknown"' 2>/dev/null)
|
|
ip=$(echo "$resp" | jq -r '.data[0].ipConfig.v4.ip // ""' 2>/dev/null)
|
|
|
|
local ping_result="—"
|
|
if [[ "$PING_CHECK" == "true" && -n "$ip" ]]; then
|
|
if ping -c 1 -W 3 "$ip" &>/dev/null; then
|
|
ping_result="reachable"
|
|
else
|
|
ping_result="unreachable"
|
|
fi
|
|
fi
|
|
|
|
case "$status" in
|
|
running) ((running++)) || true ;;
|
|
stopped) ((stopped++)) || true ;;
|
|
*) ((errored++)) || true ;;
|
|
esac
|
|
|
|
results="${results}${iid}\t${name}\t${status}\t${ip}\t${ping_result}\n"
|
|
done <<< "$ids"
|
|
|
|
if [[ "$OUTPUT_FORMAT" == "prometheus" ]]; then
|
|
cat <<EOF
|
|
# HELP contabo_fleet_instances_total Total Contabo instances
|
|
# TYPE contabo_fleet_instances_total gauge
|
|
contabo_fleet_instances_total ${total_instances}
|
|
# HELP contabo_fleet_running Running instances
|
|
# TYPE contabo_fleet_running gauge
|
|
contabo_fleet_running ${running}
|
|
# HELP contabo_fleet_stopped Stopped instances
|
|
# TYPE contabo_fleet_stopped gauge
|
|
contabo_fleet_stopped ${stopped}
|
|
# HELP contabo_fleet_error Instances in error state
|
|
# TYPE contabo_fleet_error gauge
|
|
contabo_fleet_error ${errored}
|
|
EOF
|
|
return
|
|
fi
|
|
|
|
section_header "Fleet Health Check"
|
|
|
|
if [[ "$PING_CHECK" == "true" ]]; then
|
|
printf " ${BOLD}%-13s %-20s %-11s %-16s %-12s${RESET}\n" \
|
|
"INSTANCE_ID" "NAME" "STATUS" "IP" "PING"
|
|
printf " %s\n" "$(printf '%.0s─' {1..74})"
|
|
else
|
|
printf " ${BOLD}%-13s %-20s %-11s %-16s${RESET}\n" \
|
|
"INSTANCE_ID" "NAME" "STATUS" "IP"
|
|
printf " %s\n" "$(printf '%.0s─' {1..62})"
|
|
fi
|
|
|
|
echo -e "$results" | while IFS=$'\t' read -r iid name status ip ping_res; do
|
|
[[ -z "$iid" ]] && continue
|
|
local status_color="$GREEN"
|
|
case "$status" in
|
|
running) status_color="$GREEN" ;;
|
|
stopped) status_color="$YELLOW" ;;
|
|
*) status_color="$RED" ;;
|
|
esac
|
|
|
|
if [[ "$PING_CHECK" == "true" ]]; then
|
|
local ping_color="$DIM"
|
|
case "$ping_res" in
|
|
reachable) ping_color="$GREEN" ;;
|
|
unreachable) ping_color="$RED" ;;
|
|
esac
|
|
printf " %-13s %-20s " "$iid" "${name:0:18}"
|
|
echo -ne "${status_color}"
|
|
printf "%-11s" "$status"
|
|
echo -ne "${RESET}"
|
|
printf " %-16s " "$ip"
|
|
echo -e "${ping_color}${ping_res}${RESET}"
|
|
else
|
|
printf " %-13s %-20s " "$iid" "${name:0:18}"
|
|
echo -ne "${status_color}"
|
|
printf "%-11s" "$status"
|
|
echo -e "${RESET} ${ip}"
|
|
fi
|
|
done
|
|
|
|
echo ""
|
|
field "Instances:" "$total_instances"
|
|
field_color "Running:" "${GREEN}${running}${RESET}"
|
|
if [[ "$stopped" -gt 0 ]]; then
|
|
field_color "Stopped:" "${YELLOW}${stopped}${RESET}"
|
|
else
|
|
field_color "Stopped:" "${GREEN}0${RESET}"
|
|
fi
|
|
if [[ "$errored" -gt 0 ]]; then
|
|
field_color "Error:" "${RED}${errored}${RESET}"
|
|
else
|
|
field_color "Error:" "${GREEN}0${RESET}"
|
|
fi
|
|
}
|
|
|
|
# ══════════════════════════════════════════════════════════════════════
|
|
# START / STOP / RESTART
|
|
# ══════════════════════════════════════════════════════════════════════
|
|
do_action() {
|
|
local action="$1"
|
|
local ids
|
|
ids=$(get_instance_ids)
|
|
[[ -z "$ids" ]] && die "No instances found"
|
|
|
|
if [[ "$action" != "start" && "$FORCE" != "true" ]]; then
|
|
die "${action} is destructive — use --force to confirm"
|
|
fi
|
|
|
|
local count
|
|
count=$(echo "$ids" | grep -c . || true)
|
|
local target_label="instance ${INSTANCE_ID}"
|
|
[[ "$TARGET_ALL" == "true" ]] && target_label="all (${count} instances)"
|
|
[[ -n "$TAG_ID" ]] && target_label="tag ${TAG_ID} (${count} instances)"
|
|
|
|
section_header "Bulk ${action^}"
|
|
field "Target:" "$target_label"
|
|
field "Action:" "$action"
|
|
echo ""
|
|
|
|
while IFS= read -r iid; do
|
|
[[ -z "$iid" ]] && continue
|
|
local iname
|
|
iname=$(get_instance_name "$iid")
|
|
|
|
verbose "Sending ${action} to ${iname} (${iid})"
|
|
|
|
if contabo_api POST "/compute/instances/${iid}/actions/${action}" \
|
|
-d '{}' > /dev/null 2>&1; then
|
|
echo -e " ${GREEN}✓${RESET} ${iname} (${iid}) ${action} sent"
|
|
((ACTION_OK++)) || true
|
|
else
|
|
echo -e " ${RED}✗${RESET} ${iname} (${iid}) ${action} failed"
|
|
((ACTION_FAIL++)) || true
|
|
fi
|
|
|
|
sleep 1
|
|
done <<< "$ids"
|
|
|
|
echo ""
|
|
field_color "Succeeded:" "${GREEN}${ACTION_OK}${RESET}"
|
|
if [[ "$ACTION_FAIL" -gt 0 ]]; then
|
|
field_color "Failed:" "${RED}${ACTION_FAIL}${RESET}"
|
|
fi
|
|
}
|
|
|
|
# ══════════════════════════════════════════════════════════════════════
|
|
# TAGS
|
|
# ══════════════════════════════════════════════════════════════════════
|
|
do_tags() {
|
|
if [[ "$TAG_SUB_MODE" == "list" ]]; then
|
|
local resp
|
|
resp=$(contabo_api GET "/tags?page=1&size=100")
|
|
|
|
if [[ "$OUTPUT_FORMAT" == "json" ]]; then
|
|
echo "$resp" | jq '.data // []'
|
|
return
|
|
fi
|
|
|
|
section_header "Tags"
|
|
|
|
printf " ${BOLD}%-10s %-30s %-10s${RESET}\n" "TAG_ID" "NAME" "COLOR"
|
|
printf " %s\n" "$(printf '%.0s─' {1..52})"
|
|
|
|
echo "$resp" | jq -r '.data[] | "\(.tagId)\t\(.name)\t\(.color // "—")"' 2>/dev/null \
|
|
| while IFS=$'\t' read -r tid tname tcolor; do
|
|
printf " %-10s %-30s %-10s\n" "$tid" "${tname:0:28}" "$tcolor"
|
|
done
|
|
elif [[ "$TAG_SUB_MODE" == "filter" ]]; then
|
|
[[ -z "$TAG_ID" ]] && die "Specify --filter TAG_ID"
|
|
INSTANCE_ID=""
|
|
TARGET_ALL="false"
|
|
do_inventory
|
|
else
|
|
die "Specify --list or --filter TAG_ID with --tags"
|
|
fi
|
|
}
|
|
|
|
# ══════════════════════════════════════════════════════════════════════
|
|
# HELP
|
|
# ══════════════════════════════════════════════════════════════════════
|
|
show_help() {
|
|
cat <<EOF
|
|
${BOLD}${SCRIPT_NAME}${RESET} — Contabo Fleet Manager
|
|
|
|
Inventory, health checks, and bulk operations for Contabo VPS/VDS
|
|
instances via the REST API.
|
|
|
|
${BOLD}MODES${RESET}
|
|
--inventory Dump instance inventory (table, ansible, json)
|
|
--health Health check all targeted instances
|
|
--start Start targeted instances
|
|
--stop Stop targeted instances (requires --force)
|
|
--restart Restart targeted instances (requires --force)
|
|
--tags List tags or filter instances by tag
|
|
|
|
${BOLD}TARGETING${RESET}
|
|
--instance ID Target a specific instance
|
|
--all Target all instances
|
|
--tag TAG_ID Target instances with a specific tag
|
|
|
|
${BOLD}OPTIONS${RESET}
|
|
--format FMT Output: text, json, ansible, prometheus (default: text)
|
|
--ping Include ICMP ping check in health mode
|
|
--force Required for stop/restart operations
|
|
--list List all tags (with --tags)
|
|
--filter TAG_ID Filter instances by tag (with --tags)
|
|
--verbose Debug output
|
|
--no-color Disable colored output
|
|
--help Show this help message
|
|
|
|
${BOLD}ENVIRONMENT VARIABLES${RESET}
|
|
CONTABO_CLIENT_ID OAuth2 Client ID (required)
|
|
CONTABO_CLIENT_SECRET OAuth2 Client Secret (required)
|
|
CONTABO_API_USER API username / email (required)
|
|
CONTABO_API_PASS API password (required)
|
|
CFM_FORMAT Default output format
|
|
VERBOSE Enable verbose output (true/false)
|
|
COLOR Color mode: auto, always, never
|
|
|
|
${BOLD}EXAMPLES${RESET}
|
|
# Full fleet inventory
|
|
${SCRIPT_NAME} --inventory --all
|
|
|
|
# Inventory as Ansible inventory file
|
|
${SCRIPT_NAME} --inventory --all --format ansible
|
|
|
|
# Health check all instances
|
|
${SCRIPT_NAME} --health --all
|
|
|
|
# Health check with ping
|
|
${SCRIPT_NAME} --health --all --ping
|
|
|
|
# Prometheus metrics output
|
|
${SCRIPT_NAME} --health --all --format prometheus
|
|
|
|
# Start a single instance
|
|
${SCRIPT_NAME} --start --instance 12345
|
|
|
|
# Stop all instances (requires --force)
|
|
${SCRIPT_NAME} --stop --all --force
|
|
|
|
# Restart instances by tag
|
|
${SCRIPT_NAME} --restart --tag 42 --force
|
|
|
|
# List all tags
|
|
${SCRIPT_NAME} --tags --list
|
|
|
|
# Show instances with a specific tag
|
|
${SCRIPT_NAME} --tags --filter 42
|
|
|
|
${BOLD}EXIT CODES${RESET}
|
|
0 Success
|
|
1 Runtime error
|
|
EOF
|
|
}
|
|
|
|
# ══════════════════════════════════════════════════════════════════════
|
|
# PARSE ARGS
|
|
# ══════════════════════════════════════════════════════════════════════
|
|
parse_args() {
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--inventory) RUN_MODE="inventory"; shift ;;
|
|
--health) RUN_MODE="health"; shift ;;
|
|
--start) RUN_MODE="start"; shift ;;
|
|
--stop) RUN_MODE="stop"; shift ;;
|
|
--restart) RUN_MODE="restart"; shift ;;
|
|
--tags) RUN_MODE="tags"; shift ;;
|
|
--instance) INSTANCE_ID="${2:?--instance requires an ID}"; shift 2 ;;
|
|
--all) TARGET_ALL="true"; shift ;;
|
|
--tag) TAG_ID="${2:?--tag requires a TAG_ID}"; shift 2 ;;
|
|
--format) OUTPUT_FORMAT="${2:?--format requires a value}"; shift 2 ;;
|
|
--ping) PING_CHECK="true"; shift ;;
|
|
--force) FORCE="true"; shift ;;
|
|
--list) TAG_SUB_MODE="list"; shift ;;
|
|
--filter) TAG_SUB_MODE="filter"; TAG_ID="${2:?--filter requires a TAG_ID}"; shift 2 ;;
|
|
--verbose) VERBOSE="true"; shift ;;
|
|
--no-color) COLOR="never"; shift ;;
|
|
--help|-h) setup_colors; show_help; exit 0 ;;
|
|
*) die "Unknown option: $1 (see --help)" ;;
|
|
esac
|
|
done
|
|
}
|
|
|
|
# ══════════════════════════════════════════════════════════════════════
|
|
# MAIN
|
|
# ══════════════════════════════════════════════════════════════════════
|
|
main() {
|
|
parse_args "$@"
|
|
setup_colors
|
|
|
|
if [[ -z "$RUN_MODE" ]]; then
|
|
err "No mode specified"
|
|
echo ""
|
|
show_help
|
|
exit 1
|
|
fi
|
|
|
|
check_deps
|
|
check_credentials
|
|
|
|
START_TIME=$(date +%s)
|
|
|
|
case "$RUN_MODE" in
|
|
inventory) do_inventory ;;
|
|
health) do_health ;;
|
|
start) do_action "start" ;;
|
|
stop) do_action "stop" ;;
|
|
restart) do_action "restart" ;;
|
|
tags) do_tags ;;
|
|
*) die "Unknown mode: ${RUN_MODE}" ;;
|
|
esac
|
|
|
|
if [[ "$OUTPUT_FORMAT" != "prometheus" ]]; then
|
|
echo ""
|
|
field "Duration:" "$(elapsed)"
|
|
fi
|
|
}
|
|
|
|
main "$@"
|