infra/ansible/roles/monitor/files/icinga2/scripts/incidentio-notification.sh
Graham McIntire edd689d8c7
Add incident.io alert integration for Icinga2
- New notification script (incidentio-notification.sh) that POSTs JSON
  payloads to incident.io HTTP alert sources via curl/jq
- New Icinga2 config template defining User, NotificationCommand (host
  + service), and apply Notification rules — follows the PagerDuty
  pattern with opt-in via vars.enable_incidentio
- Notification type mapping: PROBLEM/DOWN/CRITICAL/WARNING/UNKNOWN →
  firing, RECOVERY/UP/OK → resolved, ACKNOWLEDGEMENT → firing with
  metadata
- Deduplication keys: host-{name} for hosts, service-{host}-{service}
  for services
- Deployed via Ansible: script copied to /etc/icinga2/scripts/,
  config rendered to conf.d/; gated on icinga2_incidentio_token being
  defined
2026-07-24 16:36:49 -05:00

92 lines
2.5 KiB
Bash

#!/bin/bash
#
# incident.io alert notification script for Icinga2
#
# Sends host/service alerts to incident.io via their HTTP alert source API.
#
# Usage (called by Icinga2 NotificationCommand):
# incidentio-notification.sh \
# --endpoint-url <url> \
# --token <bearer-token> \
# --title <alert-title> \
# --description <alert-description> \
# --dedup-key <deduplication-key> \
# --status <icinga-notification-type> \
# [--host <hostname>] \
# [--service <servicename>]
set -euo pipefail
ENDPOINT_URL=""
TOKEN=""
TITLE=""
DESCRIPTION=""
DEDUP_KEY=""
NOTIF_STATUS=""
HOST=""
SERVICE=""
METADATA="{}"
while [ $# -gt 0 ]; do
case "$1" in
--endpoint-url) shift; ENDPOINT_URL="$1" ;;
--token) shift; TOKEN="$1" ;;
--title) shift; TITLE="$1" ;;
--description) shift; DESCRIPTION="$1" ;;
--dedup-key) shift; DEDUP_KEY="$1" ;;
--status) shift; NOTIF_STATUS="$1" ;;
--host) shift; HOST="$1" ;;
--service) shift; SERVICE="$1" ;;
*) echo "Unknown argument: $1" >&2; exit 1 ;;
esac
shift
done
# Validate required fields
if [ -z "$ENDPOINT_URL" ] || [ -z "$TOKEN" ] || [ -z "$TITLE" ] || [ -z "$DEDUP_KEY" ] || [ -z "$NOTIF_STATUS" ]; then
echo "Missing required arguments" >&2
exit 1
fi
# Map Icinga2 notification type to incident.io status
case "$NOTIF_STATUS" in
PROBLEM|DOWN|CRITICAL|WARNING|UNKNOWN)
INCIDENT_STATUS="firing"
;;
RECOVERY|UP|OK)
INCIDENT_STATUS="resolved"
;;
ACKNOWLEDGEMENT)
INCIDENT_STATUS="firing"
METADATA="$(echo "$METADATA" | jq -c '.acknowledged = true')"
;;
*)
# Default to firing for anything unrecognised
INCIDENT_STATUS="firing"
;;
esac
# Build metadata with host/service info
if [ -n "$HOST" ]; then
METADATA="$(echo "$METADATA" | jq -c --arg h "$HOST" '.host = $h')"
fi
if [ -n "$SERVICE" ]; then
METADATA="$(echo "$METADATA" | jq -c --arg s "$SERVICE" '.service = $s')"
fi
METADATA="$(echo "$METADATA" | jq -c --arg ns "$NOTIF_STATUS" '.icinga_notification_type = $ns')"
# Build JSON payload
PAYLOAD=$(jq -c -n \
--arg title "$TITLE" \
--arg description "$DESCRIPTION" \
--arg dedup_key "$DEDUP_KEY" \
--arg status "$INCIDENT_STATUS" \
--argjson metadata "$METADATA" \
'{title: $title, description: $description, deduplication_key: $dedup_key, status: $status, metadata: $metadata}'
)
# Send to incident.io
curl -s -S -X POST "$ENDPOINT_URL" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "$PAYLOAD"