#!/bin/sh -efu

PROG="${0##*/}"
PROGDIR="${0%/*}"
USERNAME=

. /bin/shell-source

ZONES_CONF=/etc/icinga2/zones.conf
DEFAULT_PORT=5665

get_object_field() {
    local obj_type="$1"
    local obj_name="$2"
    local field_name="$3"
    [ -e "$ZONES_CONF" ] || return 1
    sed -n -e '/^[[:space:]]*\/\*/,/\*\/$/ d' -e "/^[[:space:]]*object[[:space:]]\\+$obj_type[[:space:]]\\+\"\\?$obj_name\"\\?[[:space:]]\\+{/,/^[[:space:]]*}/ s/^[[:space:]]*$field_name[[:space:]]\\+=[[:space:]]\\+\\(.*\\)[[:space:]]*\$/\\1/p" "$ZONES_CONF"
}

get_parent_zone() {
    local parent_zone=
    parent_zone="$(get_object_field Zone "$1" parent)" || \
	return $?
    parent_zone="${parent_zone#\"}"
    parent_zone="${parent_zone%\"}"

    [ -n "$parent_zone" ] || return 0
    echo "$parent_zone"
}

get_zone_endpoints() {
    local endpoints=
    endpoints="$(get_object_field Zone "$1" endpoints)" || \
	return $?

    [ -n "$endpoints" ] || return 0
    echo "$endpoints" | sed -e 's/^\[[[:space:]]*//; s/[[:space:]]*\]$//; s/,[[:space:]]*/\n/g; s/"//g'
}

get_endpoint_host() {
    local host=
    host="$(get_object_field Endpoint "$1" host)" || \
	return $?

    host="${host#\"}"
    host="${host%\"}"

    [ -n "$host" ] || return 0
    echo "$host"
}

get_endpoint_port() {
    local port=
    port="$(get_object_field Endpoint "$1" port)" || \
	return $?

    port="${port#\"}"
    port="${port%\"}"

    [ -n "$port" ] || return 0
    echo "$port"
}

guess_node_name() {
    local node_name=
    node_name="$(icinga2 variable get 'NodeName')" ||:
    [ -n "$node_name" ] || node_name="${HOSTNAME:-$(hostname -s)}" ||:
    echo "$node_name"
}

guess_zone_name() {
    local zone_name=
    zone_name="$(icinga2 variable get 'ZoneName')" ||:
    [ -n "$zone_name" ] || zone_name="$(guess_node_name)" ||:
    echo "$zone_name"
}

guess_api_url() {
    local zone_name="$(guess_zone_name)"
    [ -n "$zone_name" ] || return 0

    local target_zone="$(get_parent_zone "$zone_name")"
    [ -n "$target_zone" ] || target_zone="$zone_name"

    local endpoint="$(get_zone_endpoints "$target_zone" | head -1)"
    [ -n "$endpoint" ] || endpoint="$(get_zone_endpoints ZoneName | head -1)"
    [ -n "$endpoint" ] || return 0

    if [ "$endpoint" = 'NodeName' ]; then
	endpoint="$(icinga2 variable get 'NodeName')" ||:
	[ -n "$endpoint" ] || return 0
    fi

    local host="$(get_endpoint_host "$endpoint")"
    local port="$(get_endpoint_port "$endpoint")"

    if echo "$host" | grep -q '^[0-9]\+\(\.[0-9]\+\)\{3\}$'; then
	host="$endpoint"
    fi

    [ -n "$host" ] || host="$endpoint"
    [ -n "$port" ] || port="$DEFAULT_PORT"

    echo "https://$host:$port"
}

source_if_exists "${PROGDIR:-.}/push-icinga.conf"

[ "${DISABLED:-0}" = 0 ] || exit 0

URL="${URL:-https://localhost:5665}"
HOSTNAME="${HOSTNAME:-}"
SERVICE_PREFIX_LIST="${SERVICE_PREFIX_LIST:-}"
CA="${CA:-}"
CERT="${CERT:-}"
KEY="${KEY:-}"
USERNAME="${USERNAME:-}"
PASSWORD="${PASSWORD:-}"

filter="$1"
status="$2"
message="$3"

exit_status=3
case "$status" in
    OK)
	exit_status=0
	;;
    WARNING)
	exit_status=1
	;;
    CRITICAL)
	exit_status=2
	;;
    *)
	exit_status=3
	;;
esac	

# args: URL-path [json] ...
_curl() {
    local NO_CA=
    [ -n "$CA" ] || NO_CA=1

    local url_path="$1"; shift

    local json=
    if [ $# -gt 0 ]; then
	json="$1"; shift
    fi

    (
	if [ "${DEBUG_LOG:-0}" != '0' ]; then
	    exec 1>&2
	    with_body=1
	else
	    exec 1>/dev/null
	    with_body=
	fi

	curl -sS \
	     ${NO_CA:+-k} \
	     ${CA:+--cacert "$CA"} \
	     ${CERT:+--cert "$CERT"} \
	     ${KEY:+--key "$KEY"} \
	     ${USERNAME:+-u "$USERNAME"${PASSWORD:+:"$PASSWORD"}} \
	     --fail${with_body:+-with-body} \
	     -H 'Accept: application/json' \
	     "${URL%/}"/${url_path#/} \
	     ${json:+-X POST -d "$json"} \
	     "$@"
    )
}

print_filter() {
    local host=
    host="${HOSTNAME:+host.name==\\\"$HOSTNAME\\\"}"

    local services=
    for p in $SERVICE_PREFIX_LIST; do
	[ -z "$services" ] || services="$services || "
	services="${services}service.name==\\\"$p$filter\\\""
    done

    echo "$host${host:+ && }( $services )"
}

if [ "${CLEAR_ACK:-0}" != '0' ]; then
    echo "[$PROG] Clearing acknowlegement for $filter via $URL..." >&2
    [ "${DEBUG_LOG:-0}" = '0' ] || \
	echo "[$PROG] Using filter $(print_filter)" >&2
    _curl v1/actions/remove-acknowledgement \
	  "{ \"type\": \"Service\",
	     \"filter\": \"$(print_filter)\"
	     ${CELAR_ACK_AUTHOR:+, \"author\": \"$CELAR_ACK_AUTHOR\"} }"
fi

echo "[$PROG] Sending check result for $filter via $URL..." >&2
[ "${DEBUG_LOG:-0}" = '0' ] || \
    echo "[$PROG] Using filter $(print_filter)" >&2
_curl v1/actions/process-check-result \
      "{ \"type\": \"Service\",
         \"filter\": \"$(print_filter)\",
         \"exit_status\": $exit_status,
	 \"plugin_output\": \"${message//\"/\\\"}\",
	 \"check_source\": \"$HOSTNAME\" }"
