Sync all scripts from website downloads — 352 scripts total
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.
This commit is contained in:
@@ -0,0 +1,641 @@
|
||||
#!/usr/bin/env bash
|
||||
#########################################################################################
|
||||
# #
|
||||
# OCI Free Tier Monitor #
|
||||
# Monitor Oracle Cloud Infrastructure Always Free tier usage #
|
||||
# #
|
||||
# Author: Phil Connor #
|
||||
# Contact: contact@mylinux.work #
|
||||
# License: MIT #
|
||||
# Version: 1.00 #
|
||||
# #
|
||||
#########################################################################################
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# ── Defaults ──────────────────────────────────────────────────────────────────
|
||||
|
||||
WARN_PCT="${OFT_WARN_PCT:-80}"
|
||||
CRIT_PCT="${OFT_CRIT_PCT:-95}"
|
||||
FORMAT="text"
|
||||
INTERVAL="${OFT_INTERVAL:-3600}"
|
||||
SLACK_WEBHOOK="${OFT_SLACK_WEBHOOK:-}"
|
||||
COMPARTMENT_ID="${OCI_COMPARTMENT_ID:-}"
|
||||
OCI_PROFILE="${OCI_CLI_PROFILE:-DEFAULT}"
|
||||
VERBOSE="${VERBOSE:-false}"
|
||||
COLOR="${COLOR:-auto}"
|
||||
RUN_MODE=""
|
||||
SCRIPT_NAME="$(basename "$0")"
|
||||
|
||||
# ── Always Free Limits ────────────────────────────────────────────────────────
|
||||
|
||||
LIMIT_AMD_INSTANCES=2
|
||||
LIMIT_ARM_OCPU=4
|
||||
LIMIT_ARM_RAM_GB=24
|
||||
LIMIT_BLOCK_STORAGE_GB=200
|
||||
LIMIT_VOLUME_BACKUPS=5
|
||||
LIMIT_OBJECT_STORAGE_GB=10
|
||||
LIMIT_AUTONOMOUS_DB=2
|
||||
LIMIT_LOAD_BALANCERS=1
|
||||
|
||||
# ── Colors ────────────────────────────────────────────────────────────────────
|
||||
|
||||
setup_colors() {
|
||||
if [[ "$COLOR" == "never" ]]; then
|
||||
RED="" GREEN="" YELLOW="" BLUE="" BOLD="" DIM="" RESET=""
|
||||
return
|
||||
fi
|
||||
if [[ "$COLOR" == "auto" && ! -t 1 ]]; then
|
||||
RED="" GREEN="" YELLOW="" BLUE="" BOLD="" DIM="" RESET=""
|
||||
return
|
||||
fi
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[0;33m'
|
||||
BLUE='\033[0;34m'
|
||||
BOLD='\033[1m'
|
||||
DIM='\033[2m'
|
||||
RESET='\033[0m'
|
||||
}
|
||||
|
||||
# ── Logging ───────────────────────────────────────────────────────────────────
|
||||
|
||||
log() { printf "${GREEN}%s${RESET}\n" "$*"; }
|
||||
warn() { printf "${YELLOW}⚠ %s${RESET}\n" "$*" >&2; }
|
||||
err() { printf "${RED}✗ %s${RESET}\n" "$*" >&2; }
|
||||
verbose() { [[ "$VERBOSE" == "true" ]] && printf "${DIM} %s${RESET}\n" "$*" >&2 || true; }
|
||||
die() { err "$*"; exit 1; }
|
||||
|
||||
# ── Help ──────────────────────────────────────────────────────────────────────
|
||||
|
||||
show_help() {
|
||||
cat <<EOF
|
||||
Usage: $SCRIPT_NAME [MODE] [OPTIONS]
|
||||
|
||||
Modes:
|
||||
--check Quick status check (exit 0=ok, 1=warn, 2=crit)
|
||||
--report Detailed usage report for all resources
|
||||
--watch Continuous monitoring loop
|
||||
--alerts Show only resources exceeding thresholds
|
||||
|
||||
Options:
|
||||
--format FMT Output format: text, json, prometheus (default: text)
|
||||
--warn PCT Warning threshold percentage (default: 80)
|
||||
--crit PCT Critical threshold percentage (default: 95)
|
||||
--interval SECS Watch mode poll interval in seconds (default: 3600)
|
||||
--slack-webhook URL Slack webhook URL for threshold alerts
|
||||
--compartment-id ID OCI compartment OCID (default: tenancy root)
|
||||
--no-color Disable colored output
|
||||
--verbose Debug output
|
||||
--help Show this help
|
||||
|
||||
Environment Variables:
|
||||
OCI_CLI_PROFILE OCI CLI config profile (default: DEFAULT)
|
||||
OCI_COMPARTMENT_ID Compartment OCID
|
||||
OFT_WARN_PCT Warning threshold (default: 80)
|
||||
OFT_CRIT_PCT Critical threshold (default: 95)
|
||||
OFT_SLACK_WEBHOOK Slack webhook URL
|
||||
OFT_INTERVAL Watch interval in seconds (default: 3600)
|
||||
VERBOSE Debug output (true/false)
|
||||
COLOR Color mode: auto, always, never
|
||||
|
||||
Examples:
|
||||
$SCRIPT_NAME --check
|
||||
$SCRIPT_NAME --report --format json
|
||||
$SCRIPT_NAME --watch --interval 1800 --slack-webhook "https://hooks.slack.com/..."
|
||||
$SCRIPT_NAME --alerts --warn 70 --crit 90
|
||||
$SCRIPT_NAME --report --format prometheus > /var/lib/node_exporter/textfile/oci.prom
|
||||
EOF
|
||||
}
|
||||
|
||||
# ── Argument Parsing ──────────────────────────────────────────────────────────
|
||||
|
||||
parse_args() {
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--check) RUN_MODE="check"; shift ;;
|
||||
--report) RUN_MODE="report"; shift ;;
|
||||
--watch) RUN_MODE="watch"; shift ;;
|
||||
--alerts) RUN_MODE="alerts"; shift ;;
|
||||
--format) FORMAT="$2"; shift 2 ;;
|
||||
--warn) WARN_PCT="$2"; shift 2 ;;
|
||||
--crit) CRIT_PCT="$2"; shift 2 ;;
|
||||
--interval) INTERVAL="$2"; shift 2 ;;
|
||||
--slack-webhook) SLACK_WEBHOOK="$2"; shift 2 ;;
|
||||
--compartment-id) COMPARTMENT_ID="$2"; shift 2 ;;
|
||||
--no-color) COLOR="never"; shift ;;
|
||||
--verbose) VERBOSE="true"; shift ;;
|
||||
--help) show_help; exit 0 ;;
|
||||
*) die "Unknown option: $1" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ -z "$RUN_MODE" ]]; then err "No mode specified"; echo ""; show_help; exit 1; fi
|
||||
}
|
||||
|
||||
# ── Dependency Check ──────────────────────────────────────────────────────────
|
||||
|
||||
check_deps() {
|
||||
local missing=()
|
||||
command -v oci >/dev/null 2>&1 || missing+=("oci")
|
||||
command -v jq >/dev/null 2>&1 || missing+=("jq")
|
||||
command -v curl >/dev/null 2>&1 || missing+=("curl")
|
||||
|
||||
if [[ ${#missing[@]} -gt 0 ]]; then
|
||||
die "Missing required tools: ${missing[*]}"
|
||||
fi
|
||||
|
||||
verbose "Dependencies satisfied: oci, jq, curl"
|
||||
}
|
||||
|
||||
# ── OCI Helpers ───────────────────────────────────────────────────────────────
|
||||
|
||||
oci_cmd() {
|
||||
oci --profile "$OCI_PROFILE" "$@" 2>/dev/null
|
||||
}
|
||||
|
||||
get_compartment_id() {
|
||||
if [[ -n "$COMPARTMENT_ID" ]]; then
|
||||
verbose "Using compartment: $COMPARTMENT_ID"
|
||||
return
|
||||
fi
|
||||
COMPARTMENT_ID=$(oci_cmd iam compartment list \
|
||||
--include-root \
|
||||
--query 'data[?contains("lifecycle-state", `ACTIVE`)] | [0]."compartment-id"' \
|
||||
--raw-output 2>/dev/null || true)
|
||||
|
||||
if [[ -z "$COMPARTMENT_ID" ]]; then
|
||||
COMPARTMENT_ID=$(oci_cmd iam region-subscription list \
|
||||
--query 'data[0]."tenancy-id"' --raw-output 2>/dev/null || true)
|
||||
fi
|
||||
|
||||
if [[ -z "$COMPARTMENT_ID" ]]; then
|
||||
die "Cannot determine compartment/tenancy ID. Use --compartment-id."
|
||||
fi
|
||||
|
||||
verbose "Resolved root compartment: $COMPARTMENT_ID"
|
||||
}
|
||||
|
||||
get_tenancy_name() {
|
||||
local name
|
||||
name=$(oci_cmd iam tenancy get --tenancy-id "$COMPARTMENT_ID" \
|
||||
--query 'data.name' --raw-output 2>/dev/null || echo "unknown")
|
||||
echo "$name"
|
||||
}
|
||||
|
||||
# ── Resource Check Functions ──────────────────────────────────────────────────
|
||||
|
||||
declare -A USAGE
|
||||
declare -A LIMITS
|
||||
declare -A UNITS
|
||||
|
||||
check_compute() {
|
||||
verbose "Checking compute instances..."
|
||||
|
||||
local instances
|
||||
instances=$(oci_cmd compute instance list \
|
||||
--compartment-id "$COMPARTMENT_ID" \
|
||||
--lifecycle-state RUNNING \
|
||||
--query 'data' 2>/dev/null || echo "[]")
|
||||
|
||||
local amd_count=0
|
||||
local arm_ocpu=0
|
||||
local arm_ram=0
|
||||
|
||||
while IFS= read -r line; do
|
||||
local shape
|
||||
shape=$(echo "$line" | jq -r '.shape // ""')
|
||||
if [[ "$shape" == *"A1"* ]] || [[ "$shape" == *"Ampere"* ]]; then
|
||||
local ocpu mem
|
||||
ocpu=$(echo "$line" | jq -r '."shape-config"."ocpus" // 0')
|
||||
mem=$(echo "$line" | jq -r '."shape-config"."memory-in-gbs" // 0')
|
||||
arm_ocpu=$(echo "$arm_ocpu + $ocpu" | bc)
|
||||
arm_ram=$(echo "$arm_ram + $mem" | bc)
|
||||
else
|
||||
((amd_count++)) || true
|
||||
fi
|
||||
done < <(echo "$instances" | jq -c '.[]')
|
||||
|
||||
USAGE[compute_amd]=$amd_count
|
||||
LIMITS[compute_amd]=$LIMIT_AMD_INSTANCES
|
||||
UNITS[compute_amd]="inst"
|
||||
|
||||
USAGE[compute_arm_ocpu]=$arm_ocpu
|
||||
LIMITS[compute_arm_ocpu]=$LIMIT_ARM_OCPU
|
||||
UNITS[compute_arm_ocpu]="OCPU"
|
||||
|
||||
USAGE[compute_arm_ram]=$arm_ram
|
||||
LIMITS[compute_arm_ram]=$LIMIT_ARM_RAM_GB
|
||||
UNITS[compute_arm_ram]="GB"
|
||||
|
||||
verbose " AMD instances: ${amd_count}/${LIMIT_AMD_INSTANCES}"
|
||||
verbose " Arm OCPU: ${arm_ocpu}/${LIMIT_ARM_OCPU}"
|
||||
verbose " Arm RAM: ${arm_ram}GB/${LIMIT_ARM_RAM_GB}GB"
|
||||
}
|
||||
|
||||
check_block_storage() {
|
||||
verbose "Checking block storage..."
|
||||
|
||||
local volumes
|
||||
volumes=$(oci_cmd bv volume list \
|
||||
--compartment-id "$COMPARTMENT_ID" \
|
||||
--lifecycle-state AVAILABLE \
|
||||
--query 'data' 2>/dev/null || echo "[]")
|
||||
|
||||
local total_gb=0
|
||||
while IFS= read -r size; do
|
||||
total_gb=$(echo "$total_gb + $size" | bc)
|
||||
done < <(echo "$volumes" | jq -r '.[]."size-in-gbs" // 0')
|
||||
|
||||
local backups
|
||||
backups=$(oci_cmd bv volume-backup list \
|
||||
--compartment-id "$COMPARTMENT_ID" \
|
||||
--lifecycle-state AVAILABLE \
|
||||
--query 'length(data)' 2>/dev/null || echo "0")
|
||||
|
||||
USAGE[block_storage]=$total_gb
|
||||
LIMITS[block_storage]=$LIMIT_BLOCK_STORAGE_GB
|
||||
UNITS[block_storage]="GB"
|
||||
|
||||
USAGE[volume_backups]=$backups
|
||||
LIMITS[volume_backups]=$LIMIT_VOLUME_BACKUPS
|
||||
UNITS[volume_backups]=""
|
||||
|
||||
verbose " Block storage: ${total_gb}GB/${LIMIT_BLOCK_STORAGE_GB}GB"
|
||||
verbose " Volume backups: ${backups}/${LIMIT_VOLUME_BACKUPS}"
|
||||
}
|
||||
|
||||
check_object_storage() {
|
||||
verbose "Checking object storage..."
|
||||
|
||||
local namespace
|
||||
namespace=$(oci_cmd os ns get --query 'data' --raw-output 2>/dev/null || echo "")
|
||||
|
||||
if [[ -z "$namespace" ]]; then
|
||||
warn "Cannot determine object storage namespace"
|
||||
USAGE[object_storage]=0
|
||||
LIMITS[object_storage]=$LIMIT_OBJECT_STORAGE_GB
|
||||
UNITS[object_storage]="GB"
|
||||
return
|
||||
fi
|
||||
|
||||
local buckets
|
||||
buckets=$(oci_cmd os bucket list \
|
||||
--compartment-id "$COMPARTMENT_ID" \
|
||||
--namespace-name "$namespace" \
|
||||
--query 'data[].name' 2>/dev/null || echo "[]")
|
||||
|
||||
local total_bytes=0
|
||||
while IFS= read -r bucket; do
|
||||
[[ -z "$bucket" || "$bucket" == "null" ]] && continue
|
||||
local size
|
||||
size=$(oci_cmd os bucket get \
|
||||
--namespace-name "$namespace" \
|
||||
--bucket-name "$bucket" \
|
||||
--fields "approximateSize" \
|
||||
--query 'data."approximate-size"' --raw-output 2>/dev/null || echo "0")
|
||||
[[ "$size" == "null" ]] && size=0
|
||||
total_bytes=$(echo "$total_bytes + $size" | bc)
|
||||
done < <(echo "$buckets" | jq -r '.[]')
|
||||
|
||||
local total_gb
|
||||
total_gb=$(echo "scale=1; $total_bytes / 1073741824" | bc)
|
||||
|
||||
USAGE[object_storage]=$total_gb
|
||||
LIMITS[object_storage]=$LIMIT_OBJECT_STORAGE_GB
|
||||
UNITS[object_storage]="GB"
|
||||
|
||||
verbose " Object storage: ${total_gb}GB/${LIMIT_OBJECT_STORAGE_GB}GB"
|
||||
}
|
||||
|
||||
check_autonomous_db() {
|
||||
verbose "Checking autonomous databases..."
|
||||
|
||||
local count
|
||||
count=$(oci_cmd db autonomous-database list \
|
||||
--compartment-id "$COMPARTMENT_ID" \
|
||||
--lifecycle-state AVAILABLE \
|
||||
--query 'length(data)' 2>/dev/null || echo "0")
|
||||
|
||||
USAGE[autonomous_db]=$count
|
||||
LIMITS[autonomous_db]=$LIMIT_AUTONOMOUS_DB
|
||||
UNITS[autonomous_db]=""
|
||||
|
||||
verbose " Autonomous DB: ${count}/${LIMIT_AUTONOMOUS_DB}"
|
||||
}
|
||||
|
||||
check_load_balancer() {
|
||||
verbose "Checking load balancers..."
|
||||
|
||||
local count
|
||||
count=$(oci_cmd lb load-balancer list \
|
||||
--compartment-id "$COMPARTMENT_ID" \
|
||||
--lifecycle-state ACTIVE \
|
||||
--query 'length(data)' 2>/dev/null || echo "0")
|
||||
|
||||
USAGE[load_balancers]=$count
|
||||
LIMITS[load_balancers]=$LIMIT_LOAD_BALANCERS
|
||||
UNITS[load_balancers]=""
|
||||
|
||||
verbose " Load balancers: ${count}/${LIMIT_LOAD_BALANCERS}"
|
||||
}
|
||||
|
||||
# ── Calculation ───────────────────────────────────────────────────────────────
|
||||
|
||||
calculate_pct() {
|
||||
local used="$1" limit="$2"
|
||||
if [[ "$limit" == "0" ]]; then
|
||||
echo "0"
|
||||
return
|
||||
fi
|
||||
echo "scale=0; ($used * 100) / $limit" | bc
|
||||
}
|
||||
|
||||
get_status() {
|
||||
local pct="$1"
|
||||
if (( pct >= CRIT_PCT )); then
|
||||
echo "critical"
|
||||
elif (( pct >= WARN_PCT )); then
|
||||
echo "warning"
|
||||
else
|
||||
echo "ok"
|
||||
fi
|
||||
}
|
||||
|
||||
# ── Collect All Data ──────────────────────────────────────────────────────────
|
||||
|
||||
RESOURCE_ORDER=(compute_amd compute_arm_ocpu compute_arm_ram block_storage volume_backups object_storage autonomous_db load_balancers)
|
||||
|
||||
RESOURCE_LABELS=(
|
||||
"Compute (AMD)"
|
||||
"Compute (Arm OCPU)"
|
||||
"Compute (Arm RAM)"
|
||||
"Block Storage"
|
||||
"Volume Backups"
|
||||
"Object Storage"
|
||||
"Autonomous DB"
|
||||
"Load Balancers"
|
||||
)
|
||||
|
||||
collect_all() {
|
||||
check_compute
|
||||
check_block_storage
|
||||
check_object_storage
|
||||
check_autonomous_db
|
||||
check_load_balancer
|
||||
}
|
||||
|
||||
# ── Output Formatters ─────────────────────────────────────────────────────────
|
||||
|
||||
format_text() {
|
||||
local alerts_only="${1:-false}"
|
||||
local tenancy
|
||||
tenancy=$(get_tenancy_name)
|
||||
|
||||
printf "\n${BOLD}OCI Free Tier Monitor${RESET}\n"
|
||||
printf "Tenancy: %s\n" "$tenancy"
|
||||
printf "Time: %s\n" "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
||||
printf "\n ── Resource Usage ──\n\n"
|
||||
printf " %-22s %-12s %-12s %-8s %s\n" "Resource" "Used" "Limit" "Usage" "Status"
|
||||
printf " %s\n" "$(printf '%.0s─' {1..64})"
|
||||
|
||||
local ok_count=0 warn_count=0 crit_count=0
|
||||
for i in "${!RESOURCE_ORDER[@]}"; do
|
||||
local key="${RESOURCE_ORDER[$i]}"
|
||||
local label="${RESOURCE_LABELS[$i]}"
|
||||
local used="${USAGE[$key]}"
|
||||
local limit="${LIMITS[$key]}"
|
||||
local unit="${UNITS[$key]}"
|
||||
local pct
|
||||
pct=$(calculate_pct "$used" "$limit")
|
||||
local status
|
||||
status=$(get_status "$pct")
|
||||
|
||||
case "$status" in
|
||||
ok) ((ok_count++)) || true; status_str="${GREEN}✓ OK${RESET}" ;;
|
||||
warning) ((warn_count++)) || true; status_str="${YELLOW}⚠ Warning${RESET}" ;;
|
||||
critical) ((crit_count++)) || true; status_str="${RED}✗ Critical${RESET}" ;;
|
||||
esac
|
||||
|
||||
if [[ "$alerts_only" == "true" && "$status" == "ok" ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
local used_str="${used}${unit:+ $unit}"
|
||||
local limit_str="${limit}${unit:+ $unit}"
|
||||
printf " %-22s %-12s %-12s %3s%% ${status_str}\n" \
|
||||
"$label" "$used_str" "$limit_str" "$pct"
|
||||
done
|
||||
|
||||
printf "\n Summary: %s OK, %s Warning, %s Critical\n\n" \
|
||||
"$ok_count" "$warn_count" "$crit_count"
|
||||
}
|
||||
|
||||
format_json() {
|
||||
local alerts_only="${1:-false}"
|
||||
local resources="[]"
|
||||
|
||||
for i in "${!RESOURCE_ORDER[@]}"; do
|
||||
local key="${RESOURCE_ORDER[$i]}"
|
||||
local label="${RESOURCE_LABELS[$i]}"
|
||||
local used="${USAGE[$key]}"
|
||||
local limit="${LIMITS[$key]}"
|
||||
local pct
|
||||
pct=$(calculate_pct "$used" "$limit")
|
||||
local status
|
||||
status=$(get_status "$pct")
|
||||
|
||||
if [[ "$alerts_only" == "true" && "$status" == "ok" ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
resources=$(echo "$resources" | jq \
|
||||
--arg key "$key" \
|
||||
--arg label "$label" \
|
||||
--argjson used "$used" \
|
||||
--argjson limit "$limit" \
|
||||
--argjson pct "$pct" \
|
||||
--arg status "$status" \
|
||||
'. + [{"resource": $key, "label": $label, "used": $used, "limit": $limit, "percent": $pct, "status": $status}]')
|
||||
done
|
||||
|
||||
jq -n \
|
||||
--arg time "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
|
||||
--argjson warn "$WARN_PCT" \
|
||||
--argjson crit "$CRIT_PCT" \
|
||||
--argjson resources "$resources" \
|
||||
'{"timestamp": $time, "warn_threshold": $warn, "crit_threshold": $crit, "resources": $resources}'
|
||||
}
|
||||
|
||||
format_prometheus() {
|
||||
echo "# HELP oci_free_tier_usage_percent OCI Free Tier resource usage percentage"
|
||||
echo "# TYPE oci_free_tier_usage_percent gauge"
|
||||
|
||||
for i in "${!RESOURCE_ORDER[@]}"; do
|
||||
local key="${RESOURCE_ORDER[$i]}"
|
||||
local used="${USAGE[$key]}"
|
||||
local limit="${LIMITS[$key]}"
|
||||
local pct
|
||||
pct=$(calculate_pct "$used" "$limit")
|
||||
echo "oci_free_tier_usage_percent{resource=\"${key}\"} ${pct}"
|
||||
done
|
||||
|
||||
echo "# HELP oci_free_tier_used OCI Free Tier resource current usage"
|
||||
echo "# TYPE oci_free_tier_used gauge"
|
||||
|
||||
for i in "${!RESOURCE_ORDER[@]}"; do
|
||||
local key="${RESOURCE_ORDER[$i]}"
|
||||
echo "oci_free_tier_used{resource=\"${key}\"} ${USAGE[$key]}"
|
||||
done
|
||||
|
||||
echo "# HELP oci_free_tier_limit OCI Free Tier resource limit"
|
||||
echo "# TYPE oci_free_tier_limit gauge"
|
||||
|
||||
for i in "${!RESOURCE_ORDER[@]}"; do
|
||||
local key="${RESOURCE_ORDER[$i]}"
|
||||
echo "oci_free_tier_limit{resource=\"${key}\"} ${LIMITS[$key]}"
|
||||
done
|
||||
|
||||
echo "# HELP oci_free_tier_warn_threshold Warning threshold percentage"
|
||||
echo "# TYPE oci_free_tier_warn_threshold gauge"
|
||||
echo "oci_free_tier_warn_threshold ${WARN_PCT}"
|
||||
|
||||
echo "# HELP oci_free_tier_crit_threshold Critical threshold percentage"
|
||||
echo "# TYPE oci_free_tier_crit_threshold gauge"
|
||||
echo "oci_free_tier_crit_threshold ${CRIT_PCT}"
|
||||
}
|
||||
|
||||
format_output() {
|
||||
local alerts_only="${1:-false}"
|
||||
case "$FORMAT" in
|
||||
text) format_text "$alerts_only" ;;
|
||||
json) format_json "$alerts_only" ;;
|
||||
prometheus) format_prometheus ;;
|
||||
*) die "Unknown format: $FORMAT" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# ── Slack Notification ────────────────────────────────────────────────────────
|
||||
|
||||
send_slack_alert() {
|
||||
[[ -z "$SLACK_WEBHOOK" ]] && return
|
||||
|
||||
local breached=()
|
||||
for i in "${!RESOURCE_ORDER[@]}"; do
|
||||
local key="${RESOURCE_ORDER[$i]}"
|
||||
local label="${RESOURCE_LABELS[$i]}"
|
||||
local used="${USAGE[$key]}"
|
||||
local limit="${LIMITS[$key]}"
|
||||
local pct
|
||||
pct=$(calculate_pct "$used" "$limit")
|
||||
local status
|
||||
status=$(get_status "$pct")
|
||||
|
||||
if [[ "$status" != "ok" ]]; then
|
||||
breached+=("${label}: ${used}/${limit} (${pct}%) [${status}]")
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ ${#breached[@]} -eq 0 ]]; then
|
||||
verbose "No threshold breaches — skipping Slack notification"
|
||||
return
|
||||
fi
|
||||
|
||||
local message="OCI Free Tier Alert — $(date -u +%Y-%m-%dT%H:%M:%SZ)\n"
|
||||
for line in "${breached[@]}"; do
|
||||
message+="• ${line}\n"
|
||||
done
|
||||
|
||||
local payload
|
||||
payload=$(jq -n --arg text "$message" '{"text": $text}')
|
||||
|
||||
if curl -sf -o /dev/null -X POST \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$payload" "$SLACK_WEBHOOK"; then
|
||||
verbose "Slack notification sent"
|
||||
else
|
||||
warn "Failed to send Slack notification"
|
||||
fi
|
||||
}
|
||||
|
||||
# ── Exit Code ─────────────────────────────────────────────────────────────────
|
||||
|
||||
get_exit_code() {
|
||||
local max_status="ok"
|
||||
for key in "${RESOURCE_ORDER[@]}"; do
|
||||
local used="${USAGE[$key]}"
|
||||
local limit="${LIMITS[$key]}"
|
||||
local pct
|
||||
pct=$(calculate_pct "$used" "$limit")
|
||||
local status
|
||||
status=$(get_status "$pct")
|
||||
|
||||
if [[ "$status" == "critical" ]]; then
|
||||
max_status="critical"
|
||||
break
|
||||
elif [[ "$status" == "warning" ]]; then
|
||||
max_status="warning"
|
||||
fi
|
||||
done
|
||||
|
||||
case "$max_status" in
|
||||
ok) echo 0 ;;
|
||||
warning) echo 1 ;;
|
||||
critical) echo 2 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# ── Mode Functions ────────────────────────────────────────────────────────────
|
||||
|
||||
run_check() {
|
||||
collect_all
|
||||
format_output "false"
|
||||
send_slack_alert
|
||||
local code
|
||||
code=$(get_exit_code)
|
||||
exit "$code"
|
||||
}
|
||||
|
||||
run_report() {
|
||||
collect_all
|
||||
format_output "false"
|
||||
send_slack_alert
|
||||
}
|
||||
|
||||
run_alerts() {
|
||||
collect_all
|
||||
format_output "true"
|
||||
send_slack_alert
|
||||
local code
|
||||
code=$(get_exit_code)
|
||||
exit "$code"
|
||||
}
|
||||
|
||||
run_watch() {
|
||||
log "Starting watch mode (interval: ${INTERVAL}s)"
|
||||
while true; do
|
||||
collect_all
|
||||
format_output "false"
|
||||
send_slack_alert
|
||||
verbose "Next check in ${INTERVAL}s"
|
||||
sleep "$INTERVAL"
|
||||
done
|
||||
}
|
||||
|
||||
# ── Main ──────────────────────────────────────────────────────────────────────
|
||||
|
||||
main() {
|
||||
parse_args "$@"
|
||||
setup_colors
|
||||
check_deps
|
||||
get_compartment_id
|
||||
|
||||
case "$RUN_MODE" in
|
||||
check) run_check ;;
|
||||
report) run_report ;;
|
||||
alerts) run_alerts ;;
|
||||
watch) run_watch ;;
|
||||
esac
|
||||
}
|
||||
|
||||
main "$@"
|
||||
Reference in New Issue
Block a user