From 637f14f8201e9db6ca693e090487a979e991631b Mon Sep 17 00:00:00 2001 From: Nikodemas Tuckus Date: Mon, 7 Aug 2023 11:38:53 +0200 Subject: [PATCH] Delete ssb and ggus alerting --- .github/workflows/build-go-tools.yml | 6 +- scripts/ggus_alert.sh | 43 --- scripts/ggus_alert_manage | 125 -------- scripts/ssb_alert.sh | 36 --- scripts/ssb_alert_manage | 141 --------- src/go/MONIT/ggus_alerting.go | 397 -------------------------- src/go/MONIT/ggus_parser.go | 409 --------------------------- src/go/MONIT/ssb_alerting.go | 408 -------------------------- 8 files changed, 1 insertion(+), 1564 deletions(-) delete mode 100755 scripts/ggus_alert.sh delete mode 100755 scripts/ggus_alert_manage delete mode 100755 scripts/ssb_alert.sh delete mode 100755 scripts/ssb_alert_manage delete mode 100644 src/go/MONIT/ggus_alerting.go delete mode 100644 src/go/MONIT/ggus_parser.go delete mode 100644 src/go/MONIT/ssb_alerting.go diff --git a/.github/workflows/build-go-tools.yml b/.github/workflows/build-go-tools.yml index 6a94fbac..ebb3c460 100644 --- a/.github/workflows/build-go-tools.yml +++ b/.github/workflows/build-go-tools.yml @@ -29,12 +29,8 @@ jobs: go build -o alert alert.go go build -o annotationManager annotationManager.go go build -o datasources datasources.go - go build -o ggus_alerting ggus_alerting.go - go build -o ggus_parser ggus_parser.go - go build -o ssb_alerting ssb_alerting.go go build -o es_exporter es_exporter.go - mv monit alert annotationManager datasources ggus_alerting \ - ggus_parser ssb_alerting es_exporter ../../../cmsmon-tools + mv monit alert annotationManager datasources es_exporter ../../../cmsmon-tools cd ../NATS go build -o dbs_vm dbs_vm.go go build -o nats-pub nats-pub.go diff --git a/scripts/ggus_alert.sh b/scripts/ggus_alert.sh deleted file mode 100755 index b9bd6276..00000000 --- a/scripts/ggus_alert.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/sh -##H Script for fetching GGUS Tickets and injecting them into MONIT (AlertManager) -##H Usage: ggus_alerts.sh [ggus_format] [data_file] [cmsmon_url] [interval] [vo] [timeout] [verbose]" -##H -##H Options: -##H ggus_format GGUS Query Format ("csv" or "xml") (default: "csv") -##H data_file data json file to use (default: "/tmp/ggus_data.json") -##H cmsmon_url CMS Monitoring URL (default: https://cms-monitoring.cern.ch) -##H interval Time interval for Alerts ingestion & injection (default: 1) -##H vo Required VO attribute (default: "cms") -##H timeout HTTP client timeout operation (GGUS Parser) (default:0 - zero means no timeout) -##H verbose Verbosity level (default: 0) -##H - -# Check if user is passing least required arguments. -if [ "$#" -lt 1 ]; then - cat $0 | grep "^##H" | sed -e "s,##H,,g" - exit 1 -fi - - -ggus_format=${1:-"csv"} -data_file=${2:-"/tmp/ggus_data.json"} - -## Alerting Tool optional arguments -cmsmon_url=${3:-"https://cms-monitoring.cern.ch"} -interval=${4:-1} -vo=${5:-"cms"} -## - -## GGUS Parser optional arguments -timeout=${6:-0} -## - -verbose=${7:-0} - -while true; do - echo "### ggus_parser -format $ggus_format -out $data_file -timeout $timeout -verbose $verbose" - ggus_parser -format $ggus_format -out $data_file -timeout $timeout -verbose $verbose - echo "### ggus_alerting -input $data_file -urls $cmsmon_url -vo $vo -verbose $verbose" - ggus_alerting -input $data_file -urls $cmsmon_url -vo $vo -verbose $verbose - sleep $interval -done diff --git a/scripts/ggus_alert_manage b/scripts/ggus_alert_manage deleted file mode 100755 index 10c3367e..00000000 --- a/scripts/ggus_alert_manage +++ /dev/null @@ -1,125 +0,0 @@ -##H Daemon for Alerting Tool (GGUS Ticketing System) -##H Usage: ggus_alert_manage -##H -##H Actions: -##H help help manual -##H start start the service -##H stop stop the service -##H status output service's status -##H -##H Environments: -##H GGUS_FORMAT : GGUS Query Format("csv" or "xml") default - "csv" -##H GGUSDATAFILE : Data json file to use default - /tmp/ggus_data.json -##H CMSMON_URL : CMS Monitoring URL default - https://cms-monitoring.cern.ch" -##H INTERVAL : Time interval for Alerts ingestion & injection default - 1 -##H VO : Required VO attribute default - "cms" -##H TIMEOUT : HTTP client timeout operation (GGUS Parser) default - 0 (zero means no timeout) -##H VERBOSE : Verbosity level default - 0 - -### *** -#The following block of code was taken from -#https://github.com/dmwm/deployment/blob/master/exitcodes/manage#L27 - -ME=$(basename $(dirname $0)) -TOP=$(cd $(dirname $0)/../../.. && pwd) -ROOT=$(cd $(dirname $0)/../.. && pwd) -LOGDIR=$TOP/logs/$ME - -### *** - -if [ ! -d $LOGDIR ]; then - echo "Log Directory '$LOGDIR' does not exists. creating..." - - if [ ! -w $TOP ]; then - echo "can not create $LOGDIR: $USER has no write permission for '$TOP' directory. exiting." - exit 1 - fi - - if mkdir -p $LOGDIR; then - echo "$LOGDIR created !" - else - exit 1 - fi -fi - -if [ ! -w $LOGDIR ]; then - echo "$USER has no write permission for '$LOGDIR' log directory. exiting." - exit 1 -fi - -## ggus_alert.sh arguments from Environment Variable -ggus_format=${GGUS_FORMAT:-"csv"} ## GGUS Query Format("csv" or "xml") -data_file=${GGUSDATAFILE:-"/tmp/ggus_data.json"} ## Data json file to use -cmsmon_url=${CMSMON_URL:-"https://cms-monitoring.cern.ch"} ## CMS Monitoring URL -interval=${INTERVAL:-1} ## Time interval for Alerts ingestion & injection -vo=${VO:-"cms"} ## Required VO attribute -timeout=${TIMEOUT:-0} ## HTTP client timeout operation (GGUS Parser) -verbose=${VERBOSE:-0} ## Verbosity level - -# Actions Logic -start() -{ - echo "Starting GGUS Alerting daemon." - if [ ! -x "$(command -v rotatelogs)" ]; then - echo "rotatelogs not found. Starting without it..." - nohup ggus_alert.sh $ggus_format $data_file $cmsmon_url $interval $vo $timeout $verbose 2>&1 1>& $LOGDIR/ggus_alerting-`date +%F`-`hostname -s`.log & - else - nohup ggus_alert.sh $ggus_format $data_file $cmsmon_url $interval $vo $timeout $verbose &1 | rotatelogs $LOGDIR/ggus_alerting-%Y-%m-%d-`hostname -s`.log 86400 >/dev/null 2>&1 & - fi -} - -stop() -{ - local PID=`ps auxwww | egrep "ggus_alert.sh" | grep -v grep | awk 'BEGIN{ORS=" "} {print $2}'` - echo "Stopping GGUS Alerting daemon. PID : ${PID}" - if [ -n "${PID}" ]; then - kill -9 ${PID} - fi -} - -status() -{ - local PID=`ps auxwww | egrep "ggus_alert.sh" | grep -v grep | awk 'BEGIN{ORS=" "} {print $2}'` - - if [ -z "${PID}" ]; then - echo $echo_e "GGUS Alerting daemon is INACTIVE (DEAD)" - return - fi - - if [ `uname` == "Darwin" ]; then - num_threads=`ps -M -p $PID | grep -v USER | wc -l | awk '{print $1}'` - else - num_threads=`ps -L -p $PID | grep -v PID | wc -l | awk '{print $1}'` - fi - echo "GGUS Alerting daemon running $num_threads thread(s)" - - if [ ! -z "${PID}" ]; then - echo $echo_e "GGUS Alerting daemon is ACTIVE (RUNNING), PID=${PID}" - ps -f -wwww -p ${PID} - else - echo $echo_e "GGUS Alerting daemon is INACTIVE (DEAD)" - fi -} - -# All actions -case ${1:-status} in - start) - start - ;; - - stop ) - stop - ;; - - status ) - status - ;; - - help ) - perl -ne '/^##H/ && do { s/^##H ?//; print }' < $0 - ;; - *) - echo "ggus_alert_manage: no action named '$1', please try 'ggus_alert_manage help'" 1>&2 - exit 1 - ;; -esac \ No newline at end of file diff --git a/scripts/ssb_alert.sh b/scripts/ssb_alert.sh deleted file mode 100755 index 77d8552f..00000000 --- a/scripts/ssb_alert.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/sh -##H Script for fetching CERN SSB info and injecting it into MONIT (AlertManager) -##H Usage: ssb_alerts.sh [data_file] [cmsmon_url] [interval] [verbose]" -##H -##H CMS Monit ES/InfluxDB Query -##H User's Token -##H -##H Options: -##H data_file data json file to use (default: /tmp/ssb_data.json) -##H cmsmon_url CMS Monitoring URL (default: https://cms-monitoring.cern.ch) -##H interval Time interval for Alerts ingestion & injection (default: 1) -##H verbose Verbosity level (default: 0) -##H - -# Check if user is passing least required arguments. -if [ "$#" -lt 2 ]; then - cat $0 | grep "^##H" | sed -e "s,##H,,g" - exit 1 -fi - -query="$1" -token=$2 - -# Alerting Tool optional arguments -data_file=${3:-"/tmp/ssb_data.json"} -cmsmon_url=${4:-"https://cms-monitoring.cern.ch"} -interval=${5:-1} -verbose=${6:-0} - -while true; do - echo "### monit -query=\"$query\" -dbname=monit_production_ssb_otgs -token=$token -dbid=9474" - monit -query="$query" -dbname=monit_production_ssb_otgs -token=$token -dbid=9474 > $data_file - echo "### ssb_alerting -input $data_file -url $cmsmon_url -verbose $verbose" - ssb_alerting -input $data_file -url $cmsmon_url -verbose $verbose - sleep $interval -done diff --git a/scripts/ssb_alert_manage b/scripts/ssb_alert_manage deleted file mode 100755 index b60c3512..00000000 --- a/scripts/ssb_alert_manage +++ /dev/null @@ -1,141 +0,0 @@ -##H Daemon for Alerting Tool (CERN SSB Status Board) -##H Usage: ssb_alert_manage -##H -##H Actions: -##H help help manual -##H start start the service -##H stop stop the service -##H status output service's status -##H -##H Environments: -##H QUERY : CMS Monit ES/InfluxDB Query -##H TOKEN : User's Token -##H SSBDATAFILE : Data json file to use default - /tmp/ssb_data.json -##H CMSMON_URL : CMS Monitoring URL default - https://cms-monitoring.cern.ch" -##H INTERVAL : Time interval for Alerts ingestion & injection default - 1 -##H VERBOSE : Verbosity level default - 0 - - -### *** -#The following block of code was taken from -#https://github.com/dmwm/deployment/blob/master/exitcodes/manage#L27 - -ME=$(basename $(dirname $0)) -TOP=$(cd $(dirname $0)/../../.. && pwd) -ROOT=$(cd $(dirname $0)/../.. && pwd) -LOGDIR=$TOP/logs/$ME - -### *** - -if [ -z "$QUERY" ]; then - echo "QUERY is empty. Set it as Environment Variable." - if [ -z "$TOKEN" ]; then - echo "TOKEN is empty. Set it as Environment Variable." - perl -ne '/^##H/ && do { s/^##H ?//; print }' < $0 - exit 1 - fi - perl -ne '/^##H/ && do { s/^##H ?//; print }' < $0 - exit 1 - else - if [ -z "$TOKEN" ]; then - echo "TOKEN is empty. Set it in Environment Variable." - perl -ne '/^##H/ && do { s/^##H ?//; print }' < $0 - exit 1 - fi -fi - -if [ ! -d $LOGDIR ]; then - echo "Log Directory '$LOGDIR' does not exists. creating..." - - if [ ! -w $TOP ]; then - echo "can not create $LOGDIR: $USER has no write permission for '$TOP' directory. exiting." - exit 1 - fi - - if mkdir -p $LOGDIR; then - echo "$LOGDIR created !" - else - exit 1 - fi -fi - -if [ ! -w $LOGDIR ]; then - echo "$USER has no write permission for '$LOGDIR' log directory. exiting." - exit 1 -fi - -## ssb_alert.sh arguments from Environment Variable -query=$QUERY ## CMS Monit InfluxDB Query -token=$TOKEN ## User's Token -data_file=${SSBDATAFILE:-"/tmp/ssb_data.json"} ## Data json file to use -cmsmon_url=${CMSMON_URL:-"https://cms-monitoring.cern.ch"} ## CMS Monitoring URL -interval=${INTERVAL:-1} ## Time interval for Alerts ingestion & injection -verbose=${VERBOSE:-0} ## Verbosity level - -# Actions Logic -start() -{ - echo "Starting SSB Alerting daemon." - if [ ! -x "$(command -v rotatelogs)" ]; then - echo "rotatelogs not found. Starting without it..." - nohup ssb_alert.sh "$query" $token $data_file $cmsmon_url $interval $verbose 2>&1 1>& $LOGDIR/ssb_alerting-`date +%F`-`hostname -s`.log & - else - nohup ssb_alert.sh "$query" $token $data_file $cmsmon_url $interval $verbose &1 | rotatelogs $LOGDIR/ssb_alerting-%Y-%m-%d-`hostname -s`.log 86400 >/dev/null 2>&1 & - fi -} - -stop() -{ - local PID=`ps auxwww | egrep "ssb_alert.sh" | grep -v grep | awk 'BEGIN{ORS=" "} {print $2}'` - echo "Stopping SSB Alerting daemon. PID : ${PID}" - if [ -n "${PID}" ]; then - kill -9 ${PID} - fi -} - -status() -{ - local PID=`ps auxwww | egrep "ssb_alert.sh" | grep -v grep | awk 'BEGIN{ORS=" "} {print $2}'` - - if [ -z "${PID}" ]; then - echo $echo_e "SSB Alerting daemon is INACTIVE (DEAD)" - return - fi - - if [ `uname` == "Darwin" ]; then - num_threads=`ps -M -p $PID | grep -v USER | wc -l | awk '{print $1}'` - else - num_threads=`ps -L -p $PID | grep -v PID | wc -l | awk '{print $1}'` - fi - echo "SSB Alerting daemon running $num_threads thread(s)" - - if [ ! -z "${PID}" ]; then - echo $echo_e "SSB Alerting daemon is ACTIVE (RUNNING), PID=${PID}" - ps -f -wwww -p ${PID} - else - echo $echo_e "SSB Alerting daemon is INACTIVE (DEAD)" - fi -} - -# All actions -case ${1:-status} in - start) - start - ;; - - stop ) - stop - ;; - - status ) - status - ;; - - help ) - perl -ne '/^##H/ && do { s/^##H ?//; print }' < $0 - ;; - *) - echo "ssb_alert_manage: no action named '$1', please try 'ssb_alert_manage help'" 1>&2 - exit 1 - ;; -esac diff --git a/src/go/MONIT/ggus_alerting.go b/src/go/MONIT/ggus_alerting.go deleted file mode 100644 index 650e544d..00000000 --- a/src/go/MONIT/ggus_alerting.go +++ /dev/null @@ -1,397 +0,0 @@ -package main - -import ( - "bytes" - "encoding/json" - "flag" - "fmt" - "io" - "log" - "net/http" - "net/http/httputil" - "os" - "strconv" - "strings" - "time" -) - -// File : ggus_alerting.go -// Author : Rahul Indra -// Created : Thu, 21 May 2020 21:07:32 GMT -// Description: GGUS Alerting Module for CERN MONIT infrastructure - -// URLs for AlertManager Instances -var alertManagerURLs string - -// List of URLs for AlertManager Instances -var alertManagerURLList []string - -// severity of alerts -var severity string - -// tag name -var tag string - -// service name -var service string - -// Required VO attribute -var vo string - -// verbose defines verbosity level -var verbose int - -// (max) duration of alert timestamp in hours -var duration int64 = 24 - -// Map for storing Existing Tickets -var exstTkt map[string]int - -// GGUS Data Struct -type ggus []struct { - TicketID int `json:"TicketID"` - Type string `json:"Type"` - VO string `json:"VO"` - Site string `json:"Site"` - Priority string `json:"Priority"` - ResponsibleUnit string `json:"ResponsibleUnit"` - Status string `json:"Status"` - LastUpdate string `json:"LastUpdate"` - Subject string `json:"Subject"` - Scope string `json:"Scope"` -} - -// AlertManager API acceptable JSON Data for GGUS Data -type amJSON struct { - Labels struct { - Alertname string `json:"alertname"` - Severity string `json:"severity"` - Service string `json:"service"` - Tag string `json:"tag"` - Priority string `json:"Priority"` - Scope string `json:"Scope"` - Site string `json:"Site"` - VO string `json:"VO"` - Type string `json:"Type"` - } `json:"labels"` - Annotations struct { - Priority string `json:"Priority"` - ResponsibleUnit string `json:"ResponsibleUnit"` - Scope string `json:"Scope"` - Site string `json:"Site"` - Status string `json:"Status"` - Subject string `json:"Subject"` - TicketID string `json:"TicketID"` - Type string `json:"Type"` - VO string `json:"VO"` - URL string `json:"URL"` - } `json:"annotations"` - StartsAt time.Time `json:"startsAt"` - EndsAt time.Time `json:"endsAt"` -} - -// AlertManager GET API acceptable JSON Data struct for GGUS data -type ggusData struct { - Data []amJSON -} - -// function for parsing JSON data from GGUS Data -func (data *ggus) parseJSON(jsondata []byte) { - err := json.Unmarshal(jsondata, &data) - if err != nil { - log.Printf("Unable to parse GGUS JSON data, error: %v\n", err) - } -} - -// function for fetching JSON data from GGUS Data -func fetchJSON(filename string) []byte { - file, err := os.Open(filename) - if err != nil { - log.Printf("Unable to open JSON file, error: %v\n", err) - } - - defer file.Close() - - jsonData, err := io.ReadAll(file) - if err != nil { - log.Printf("Unable to read JSON file, error: %v\n", err) - } - - if verbose > 1 { - log.Println("GGUS Data: " + string(jsonData)) - } - - return jsonData - -} - -// function for converting SSB JSON Data into JSON Data required by AlertManager APIs. -func convertData(data ggus) []byte { - - var temp amJSON - var finalData []amJSON - - exstTkt = make(map[string]int) - - for _, each := range data { - - // Ignoring all tickets whose VO is not "cms" - if each.VO != vo { - continue - } - - exstTkt[strconv.Itoa(each.TicketID)] = 1 - - begin, errInt := strconv.ParseInt(each.LastUpdate, 10, 64) - if errInt != nil { - log.Printf("Unable to convert LastUpdate string to int64, error: %v\n", errInt) - } - - _beginRFC3339 := time.Unix(begin, 0).UTC() - - temp.Labels.Alertname = "ggus-" + strconv.Itoa(each.TicketID) - temp.Labels.Severity = severity - temp.Labels.Service = service - temp.Labels.Tag = tag - temp.Labels.Type = each.Type - temp.Labels.VO = each.VO - temp.Labels.Site = each.Site - temp.Labels.Priority = each.Priority - temp.Labels.Scope = each.Scope - - temp.Annotations.TicketID = strconv.Itoa(each.TicketID) - temp.Annotations.Type = each.Type - temp.Annotations.VO = each.VO - temp.Annotations.Site = each.Site - temp.Annotations.Priority = each.Priority - temp.Annotations.ResponsibleUnit = each.ResponsibleUnit - temp.Annotations.Status = each.Status - temp.Annotations.Subject = each.Subject - temp.Annotations.Scope = each.Scope - temp.Annotations.URL = "https://ggus.eu/?mode=ticket_info&ticket_id=" + strconv.Itoa(each.TicketID) - - temp.StartsAt = _beginRFC3339 - temp.EndsAt = time.Unix(int64(_beginRFC3339.Unix()+duration), 0).UTC() - - if verbose > 0 { - log.Println("adding", temp.Labels.Alertname, temp.Labels.Severity, temp.Labels.Service, temp.Labels.Tag, temp.Annotations.URL) - } - finalData = append(finalData, temp) - - } - - jsonStr, err := json.Marshal(finalData) - - if err != nil { - log.Printf("Unable to convert JSON Data, error: %v\n", err) - } - - return jsonStr - -} - -// helper function for parsing list of alertmanager urls separated by comma -func parseURLs(urls string) []string { - var urlList []string - for _, url := range strings.Split(urls, ",") { - urlList = append(urlList, strings.Trim(url, " ")) - } - return urlList -} - -// function for get request on /api/v1/alerts alertmanager endpoint for fetching alerts. -func get(alertManagerURL string) *ggusData { - - var data *ggusData - - //GET API for fetching only GGUS alerts. - apiurl := alertManagerURL + "/api/v1/alerts?active=true&silenced=false&inhibited=false&unprocessed=false&filter=tag=\"GGUS\"" - - req, err := http.NewRequest("GET", apiurl, nil) - req.Header.Add("Accept-Encoding", "identity") - req.Header.Add("Accept", "application/json") - - client := &http.Client{} - - if verbose > 1 { - dump, err := httputil.DumpRequestOut(req, true) - if err == nil { - log.Println("Request: ", string(dump)) - } - } - - resp, err := client.Do(req) - if err != nil { - panic(err) - } - defer resp.Body.Close() - - byteValue, err := io.ReadAll(resp.Body) - - if err != nil { - log.Printf("Unable to read JSON Data from AlertManager GET API, error: %v\n", err) - return data - } - - err = json.Unmarshal(byteValue, &data) - if err != nil { - log.Printf("Unable to parse JSON Data from AlertManager GET API, error: %v\n", err) - return data - } - - if verbose > 1 { - dump, err := httputil.DumpResponse(resp, true) - if err == nil { - log.Println("Response: ", string(dump)) - } - } - - return data - -} - -// function for making post request on /api/v1/alerts alertmanager endpoint for creating alerts. -func post(jsonStr []byte, alertManagerURL string) { - apiurl := alertManagerURL + "/api/v1/alerts" - - req, err := http.NewRequest("POST", apiurl, bytes.NewBuffer(jsonStr)) - req.Header.Set("Content-Type", "application/json") - - client := &http.Client{} - - if verbose > 1 { - dump, err := httputil.DumpRequestOut(req, true) - if err == nil { - log.Println("Request: ", string(dump)) - } - } - - resp, err := client.Do(req) - if err != nil { - panic(err) - } - defer resp.Body.Close() - - if verbose > 1 { - dump, err := httputil.DumpResponse(resp, true) - if err == nil { - log.Println("Response: ", string(dump)) - } - } -} - -// Function to end alerts for tickets which are resolved -func deleteAlerts(alertManagerURL string) { - amData := get(alertManagerURL) - var temp amJSON - var finalData []amJSON - - for _, each := range amData.Data { - - // If tickets which are in Existing Ticket Map then no need to send End Time, We Skip. - if exstTkt[each.Annotations.TicketID] == 1 { - continue - } - - temp.Labels.Alertname = each.Labels.Alertname - temp.Labels.Severity = each.Labels.Severity - temp.Labels.Service = each.Labels.Service - temp.Labels.Tag = each.Labels.Tag - temp.Labels.Type = each.Labels.Type - temp.Labels.VO = each.Labels.VO - temp.Labels.Site = each.Labels.Site - temp.Labels.Priority = each.Labels.Priority - temp.Labels.Scope = each.Labels.Scope - - temp.Annotations.TicketID = each.Annotations.TicketID - temp.Annotations.Type = each.Annotations.Type - temp.Annotations.VO = each.Annotations.VO - temp.Annotations.Site = each.Annotations.Site - temp.Annotations.Priority = each.Annotations.Priority - temp.Annotations.ResponsibleUnit = each.Annotations.ResponsibleUnit - temp.Annotations.Status = each.Annotations.Status - temp.Annotations.Subject = each.Annotations.Subject - temp.Annotations.Scope = each.Annotations.Scope - temp.Annotations.URL = each.Annotations.URL - - temp.StartsAt = each.StartsAt - temp.EndsAt = time.Now().UTC() - - //Checking if Start Time is Afer Time Right now, maybe false alert added by mistake. **Corner Case to be handled** - if each.StartsAt.Before(temp.EndsAt) == false { - temp.StartsAt = time.Now().UTC() - temp.EndsAt = time.Now().UTC() - } - - finalData = append(finalData, temp) - } - - jsonStr, err := json.Marshal(finalData) - if err != nil { - log.Printf("Unable to convert JSON Data, error: %v\n", err) - } - - if verbose > 1 { - fmt.Println("Deleted Alerts: ", string(jsonStr)) - } - - post(jsonStr, alertManagerURL) -} - -// Machine Learning Logic for Categorizing GGUS Tickets -func categorizeTicket() { - // To be Implemented -} - -// function containing all logics for alerting. -func alert(inp string, dryRun bool) { - - alertManagerURLList = parseURLs(alertManagerURLs) - jsonData := fetchJSON(inp) - var data ggus - data.parseJSON(jsonData) - jsonStrAM := convertData(data) //JSON data in AlertManager APIs format. - if dryRun { - fmt.Println(string(jsonStrAM)) - return - } - - for _, alertManagerURL := range alertManagerURLList { - post(jsonStrAM, alertManagerURL) - deleteAlerts(alertManagerURL) - } - -} - -func main() { - - var inp string - severity = "ticket" // TODO: replace with severity level from ticket annotation - tag = "monitoring" - service = "GGUS" - var dryRun bool - - flag.StringVar(&inp, "input", "", "input filename") - flag.StringVar(&vo, "vo", "cms", "Required VO attribute in GGUS Ticket") - flag.StringVar(&alertManagerURLs, "urls", "", "list of alertmanager URLs seperated by commas") - flag.IntVar(&verbose, "verbose", 0, "verbosity level") - flag.BoolVar(&dryRun, "dryRun", false, "dry run mode, fetch data but do not post it to AM") - flag.Int64Var(&duration, "duration", 24, "max alert duration in hours") - flag.Parse() - - if inp == "" { - log.Fatalf("Input filename missing. Exiting....") - } - - if alertManagerURLs == "" { - log.Fatalf("AlertManager URLs missing. Exiting....") - } - - if verbose > 0 { - log.SetFlags(log.LstdFlags | log.Lshortfile) - } else { - log.SetFlags(log.LstdFlags) - } - - alert(inp, dryRun) -} diff --git a/src/go/MONIT/ggus_parser.go b/src/go/MONIT/ggus_parser.go deleted file mode 100644 index 72a605ad..00000000 --- a/src/go/MONIT/ggus_parser.go +++ /dev/null @@ -1,409 +0,0 @@ -package main - -import ( - "bytes" - "crypto/tls" - "encoding/csv" - "encoding/json" - "encoding/xml" - "flag" - "fmt" - "github.com/PuerkitoBio/goquery" - "io" - "log" - "net/http" - "net/http/httputil" - "os" - "os/user" - "regexp" - "strconv" - "strings" - "sync" - "time" - - "github.com/vkuznet/x509proxy" -) - -// File : ggus_parser.go -// Author : Rahul Indra -// Created : Thu, 07 May 2020 13:34:15 GMT -// Description: Parser for CERN MONIT infrastructure - -// Timeout defines timeout for net/url request -var Timeout int - -// Verbose defines verbosity level -var Verbose int - -// TicketsXML Data struct -type TicketsXML struct { - Ticket []struct { - TicketID int `xml:"Ticket-ID"` - Type string `xml:"Type"` - VO string `xml:"VO"` - Site string `xml:"Site"` - Priority string `xml:"Priority"` - ResponsibleUnit string `xml:"Responsible_Unit"` - Status string `xml:"Status"` - LastUpdate string `xml:"Last_Update"` - Subject string `xml:"Subject"` - Scope string `xml:"Scope"` - Description string - Comments []TicketComment - } `xml:"ticket"` -} - -type TicketComment struct { - Date string - Time string - Text string -} - -// Ticket Data struct (CSV) -type Ticket struct { - TicketID int - Type *string - VO *string - Site *string - Priority *string - ResponsibleUnit *string - Status *string - LastUpdate string - Subject *string - Scope *string -} - -// function for eliminating "none" or empty values in JSON -func nullValueHelper(value **string, data string) { - - if data == "none" || data == "" { - *value = nil - } else { - *value = &data - } -} - -func convertTime(timestamp string) int64 { - - UnixTS, errTime := time.Parse(time.RFC3339, strings.ReplaceAll(timestamp, " ", "T")+"Z") - if errTime != nil { - log.Printf("Unable to parse LastUpdate TimeStamp, error: %v\n", errTime) - } - - return UnixTS.Unix() -} - -// function for unpacking the CSV data into Ticket Data struct -func parseCSV(data io.ReadCloser) []Ticket { - var ticket Ticket - var tickets []Ticket - - reader := csv.NewReader(data) - reader.Comma = ';' - reader.LazyQuotes = true - csvData, err := reader.ReadAll() - if err != nil { - log.Fatalf("Unable to read CSV file, error: %v\n", err) - } - - for ind := range csvData { - - if ind > 0 { - - ticket.TicketID, _ = strconv.Atoi(csvData[ind][0]) - - nullValueHelper(&ticket.Type, csvData[ind][1]) - nullValueHelper(&ticket.VO, csvData[ind][2]) - nullValueHelper(&ticket.Site, csvData[ind][3]) - nullValueHelper(&ticket.Priority, csvData[ind][4]) - nullValueHelper(&ticket.ResponsibleUnit, csvData[ind][5]) - nullValueHelper(&ticket.Status, csvData[ind][6]) - - ticket.LastUpdate = strconv.FormatInt(convertTime(csvData[ind][7]), 10) - - nullValueHelper(&ticket.Subject, csvData[ind][8]) - nullValueHelper(&ticket.Scope, csvData[ind][9]) - tickets = append(tickets, ticket) - } - } - return tickets -} - -// function for unpacking the XML data into TicketsXML Data struct -func (tXml *TicketsXML) parseXML(data io.ReadCloser) { - - byteValue, err := io.ReadAll(data) - if err != nil { - log.Printf("Unable to read XML Data, error: %v\n", err) - return - } - - d := xml.NewDecoder(bytes.NewReader(byteValue)) - d.Strict = false - - errp := d.Decode(&tXml) - if errp != nil { - log.Printf("Unable to parse XML Data, error: %v\n", errp) - return - } - - for ind := range tXml.Ticket { - tXml.Ticket[ind].LastUpdate = strconv.FormatInt(convertTime(tXml.Ticket[ind].LastUpdate), 10) - } - -} - -// function for output the processed data into JSON format -func saveJSON(data interface{}, out string) error { - - jsonData, err := json.Marshal(data) - if err != nil { - log.Printf("Unable to convert into JSON format, error: %v\n", err) - return err - } - - jsonFile, err := os.Create(out) - if err != nil { - fmt.Printf("Unable to create JSON file, error: %v\n", err) - return err - } - defer jsonFile.Close() - - jsonFile.Write(jsonData) - jsonFile.Close() - - return nil - -} - -// -// The following block of code was taken from -// https://github.com/dmwm/das2go/blob/master/utils/fetch.go#L75 - -// TLSCertsRenewInterval controls interval to re-read TLS certs (in seconds) -var TLSCertsRenewInterval time.Duration - -// TLSCertsManager holds TLS certificates for the server -type TLSCertsManager struct { - Certs []tls.Certificate - Expire time.Time -} - -// GetCerts return fresh copy of certificates -func (t *TLSCertsManager) GetCerts() ([]tls.Certificate, error) { - var lock = sync.Mutex{} - lock.Lock() - defer lock.Unlock() - // we'll use existing certs if our window is not expired - if t.Certs == nil || time.Since(t.Expire) > TLSCertsRenewInterval { - if Verbose > 0 { - log.Println("read new certs with expire", t.Expire) - } - t.Expire = time.Now() - certs, err := tlsCerts() - if err == nil { - t.Certs = certs - } else { - panic(err.Error()) - } - } - return t.Certs, nil -} - -// global TLSCerts manager -var tlsManager TLSCertsManager - -// client X509 certificates -func tlsCerts() ([]tls.Certificate, error) { - uproxy := os.Getenv("X509_USER_PROXY") - uckey := os.Getenv("X509_USER_KEY") - ucert := os.Getenv("X509_USER_CERT") - // check if /tmp/x509up_u$UID exists, if so setup X509_USER_PROXY env - u, err := user.Current() - if err == nil { - fname := fmt.Sprintf("/tmp/x509up_u%s", u.Uid) - if _, err := os.Stat(fname); err == nil { - uproxy = fname - } - } - - if uproxy == "" && uckey == "" { // user doesn't have neither proxy or user certs - return nil, nil - } - if uproxy != "" { - // use local implementation of LoadX409KeyPair instead of tls one - x509cert, err := x509proxy.LoadX509Proxy(uproxy) - if err != nil { - return nil, fmt.Errorf("failed to parse X509 proxy: %v", err) - } - - certs := []tls.Certificate{x509cert} - return certs, nil - } - x509cert, err := tls.LoadX509KeyPair(ucert, uckey) - if err != nil { - return nil, fmt.Errorf("failed to parse user X509 certificate: %v", err) - } - - certs := []tls.Certificate{x509cert} - return certs, nil -} - -// HTTPClient is HTTP client for urlfetch server -func HTTPClient() *http.Client { - // get X509 certs - certs, err := tlsManager.GetCerts() - if err != nil { - panic(err.Error()) - } - - timeout := time.Duration(Timeout) * time.Second - if len(certs) == 0 { - if Timeout > 0 { - return &http.Client{Timeout: time.Duration(timeout)} - } - return &http.Client{} - } - tr := &http.Transport{ - TLSClientConfig: &tls.Config{Certificates: certs, - InsecureSkipVerify: true}, - } - if Timeout > 0 { - return &http.Client{Transport: tr, Timeout: timeout} - } - return &http.Client{Transport: tr} -} - -func ggusRequest(url, accept string) *http.Response { - var req *http.Request - req, _ = http.NewRequest("GET", url, nil) - req.Header.Add("Accept-Encoding", "identity") - req.Header.Add("Accept", accept) - - client := HTTPClient() - - if Verbose > 1 { - dump, err := httputil.DumpRequestOut(req, true) - if err == nil { - log.Println("request: ", string(dump)) - } - } - - resp, err := client.Do(req) - - if err != nil { - log.Println(err) - } - - if Verbose > 1 { - dump, err := httputil.DumpResponse(resp, true) - if err == nil { - log.Println("response:", string(dump)) - } - } - - return resp -} - -func cleanText(t string) string { - r, err := regexp.Compile("[\t\n\r ]+") - if err != nil { - log.Panic(err) - } - - return strings.Trim(r.ReplaceAllString(t, " "), " ") -} - -func retrieveTicketDetails(ticketId int) (string, []TicketComment) { - url := fmt.Sprintf("https://ggus.eu/?mode=ticket_info&ticket_id=%d", ticketId) - resp := ggusRequest(url, "text/html") - - doc, err := goquery.NewDocumentFromReader(resp.Body) - if err != nil { - log.Println(err.Error()) - return "", []TicketComment{} - } - - description := "" - var comments []TicketComment - - s := "tr .ticket_info_h4" - doc.Find(s).Each(func(i int, selection *goquery.Selection) { - selection.Siblings().Each(func(j int, selection *goquery.Selection) { - if i == 0 { - description = description + cleanText(selection.Text()) - } else if i == 1 { - selection.Find("tr[class=ticket_info_innertable],tr[class=ticket_info_innertable_light]").Each(func(i int, selection *goquery.Selection) { - comment := TicketComment{} - selection.Children().Each(func(i int, selection *goquery.Selection) { - ct := cleanText(selection.Text()) - switch i { - case 0: - comment.Date = ct - case 1: - comment.Time = ct - case 2: - comment.Text = ct - } - }) - comments = append(comments, comment) - }) - } - }) - }) - - return description, comments -} - -// processResponse function for fetching data from GGUS endpoint and dumping it into JSON format -func processResponse(url, format, accept, out string, detailed bool) { - resp := ggusRequest(url, accept) - defer resp.Body.Close() - - if format == "csv" { - data := parseCSV(resp.Body) - - saveJSON(data, out) - } else if format == "xml" { - data := &TicketsXML{} - data.parseXML(resp.Body) - - if detailed { - for t := range data.Ticket { - description, comments := retrieveTicketDetails(data.Ticket[t].TicketID) - data.Ticket[t].Description = description - data.Ticket[t].Comments = comments - } - } - - saveJSON(data.Ticket, out) - } -} - -func main() { - var format string - var out string - var detailed bool - flag.StringVar(&format, "format", "csv", "GGUS data-format to use (csv or xml)") - flag.StringVar(&out, "out", "", "out filename") - flag.IntVar(&Verbose, "verbose", 0, "verbosity level") - flag.IntVar(&Timeout, "timeout", 0, "http client timeout operation, zero means no timeout") - flag.BoolVar(&detailed, "detailed", false, "whether to fetch the detailed description and comments for tickets, might take a while") - flag.Parse() - - ggus := "https://ggus.eu/?mode=ticket_search&status=open&date_type=creation+date&tf_radio=1&timeframe=any&orderticketsby=REQUEST_ID&orderhow=desc" - var accept string - if format == "csv" { - ggus = ggus + "&writeFormat=CSV" - accept = "text/csv" - } else if format == "xml" { - ggus = ggus + "&writeFormat=XML" - accept = "text/xml" - } - - if out == "" { - log.Fatalf("Output filename missing. Exiting....") - } - - processResponse(ggus, format, accept, out, detailed) -} diff --git a/src/go/MONIT/ssb_alerting.go b/src/go/MONIT/ssb_alerting.go deleted file mode 100644 index 35bef028..00000000 --- a/src/go/MONIT/ssb_alerting.go +++ /dev/null @@ -1,408 +0,0 @@ -package main - -import ( - "bytes" - "encoding/json" - "flag" - "fmt" - "io" - "log" - "net/http" - "net/http/httputil" - "os" - "strings" - "time" -) - -// File : ssb_alerting.go -// Author : Rahul Indra -// Created : Thu, 16 May 2020 16:45:00 GMT -// Description: SSB Alerting Module for CERN MONIT infrastructure - -// URLs for AlertManager Instances -var alertManagerURLs string - -// List of URLs for AlertManager Instances -var alertManagerURLList []string - -// severity of alerts -var severity string - -// tag name -var tag string - -// service name -var service string - -// verbose defines verbosity level -var verbose int - -// (max) duration of alert timestamp in hours -var duration int64 = 24 - -// Map for storing Existing SSB Data -var exstSSBData map[string]int - -// CERN SSB Data Struct -type ssb struct { - Results []struct { - Series []struct { - Columns []string `json:"columns"` - Name string `json:"name"` - Values [][]interface{} `json:"values"` - } `json:"series"` - StatementID int `json:"statement_id"` - } `json:"results"` -} - -// AlertManager API acceptable JSON Data for CERN SSB Data -type amJSON struct { - Labels struct { - Alertname string `json:"alertname"` - Severity string `json:"severity"` - Service string `json:"service"` - Tag string `json:"tag"` - Type string `json:"type"` - Description string `json:"description"` - FeName string `json:"feName"` - SeName string `json:"seName"` - } `json:"labels"` - Annotations struct { - Date string `json:"date"` - Description string `json:"description"` - FeName string `json:"feName"` - MonitState string `json:"monitState"` - MonitState1 string `json:"monitState1"` - SeName string `json:"seName"` - ShortDescription string `json:"shortDescription"` - SsbNumber string `json:"ssbNumber"` - SysCreatedBy string `json:"sysCreatedBy"` - SysModCount string `json:"sysModCount"` - SysUpdatedBy string `json:"sysUpdatedBy"` - Type string `json:"type"` - UpdateTimestamp time.Time `json:"updateTimestamp"` - URL string `json:"URL"` - } `json:"annotations"` - StartsAt time.Time `json:"startsAt"` - EndsAt time.Time `json:"endsAt"` -} - -// AlertManager GET API acceptable JSON Data struct for SSB data -type ssbData struct { - Data []amJSON -} - -// function for parsing JSON data from CERN SSB Data -func (data *ssb) parseJSON(jsondata []byte) { - err := json.Unmarshal(jsondata, &data) - if err != nil { - log.Printf("Unable to parse CERN SSB JSON data, error: %v\n", err) - } -} - -// function for fetching JSON data from CERN SSB Data -func fetchJSON(filename string) []byte { - file, err := os.Open(filename) - if err != nil { - log.Printf("Unable to open JSON file, error: %v\n", err) - } - - defer file.Close() - - jsonData, err := io.ReadAll(file) - if err != nil { - log.Printf("Unable to read JSON file, error: %v\n", err) - } - - if verbose > 1 { - log.Println("CERN SSB Data: " + string(jsonData)) - } - - return jsonData - -} - -// function for eliminating "none" or empty values ("null") in JSON -func nullValueChecker(target *string, data interface{}) { - - if b, ok := data.(string); ok { - *target = b - } -} - -// function for converting SSB JSON Data into JSON Data required by AlertManager APIs. -func (data *ssb) convertData() []byte { - - var finalData []amJSON - exstSSBData = make(map[string]int) - - for _, each := range data.Results[0].Series[0].Values { - var temp amJSON - var _beginTS, _endTS, _updateTS time.Time - var ssbNum string - nullValueChecker(&ssbNum, each[10]) - - exstSSBData[ssbNum] = 1 - - if b, ok := each[1].(float64); ok { - _beginTS = time.Unix(0, int64(b)*int64(time.Millisecond)).UTC() - } - - if e, ok := each[4].(float64); ok { - _endTS = time.Unix(0, int64(e)*int64(time.Millisecond)).UTC() - - } else { - // If not given EndTime the alert will have max duration from current timestamp - current := time.Now().UTC() - _endTS = time.Unix(int64(current.Unix()+duration), 0).UTC() - } - - if u, ok := each[15].(float64); ok { - _updateTS = time.Unix(0, int64(u)*int64(time.Millisecond)).UTC() - } - - temp.Labels.Alertname = "ssb-" + ssbNum //ssbNumber as an unique key for alertname - temp.Labels.Severity = severity - temp.Labels.Service = service - temp.Labels.Tag = tag - nullValueChecker(&temp.Labels.Description, each[2]) - nullValueChecker(&temp.Labels.FeName, each[5]) - nullValueChecker(&temp.Labels.SeName, each[8]) - nullValueChecker(&temp.Labels.Type, each[14]) - - nullValueChecker(&temp.Annotations.Date, each[0]) - nullValueChecker(&temp.Annotations.Description, each[2]) - nullValueChecker(&temp.Annotations.FeName, each[5]) - nullValueChecker(&temp.Annotations.MonitState, each[6]) - nullValueChecker(&temp.Annotations.MonitState1, each[7]) - nullValueChecker(&temp.Annotations.SeName, each[8]) - nullValueChecker(&temp.Annotations.ShortDescription, each[9]) - nullValueChecker(&temp.Annotations.SsbNumber, each[10]) - nullValueChecker(&temp.Annotations.SysCreatedBy, each[11]) - nullValueChecker(&temp.Annotations.SysModCount, each[12]) - nullValueChecker(&temp.Annotations.SysUpdatedBy, each[13]) - nullValueChecker(&temp.Annotations.Type, each[14]) - - temp.Annotations.UpdateTimestamp = _updateTS - temp.Annotations.URL = "https://cern.service-now.com/service-portal?id=outage&n=" + temp.Annotations.SsbNumber - - temp.StartsAt = _beginTS - temp.EndsAt = _endTS - - if verbose > 0 { - log.Println("adding", temp.Labels.Alertname, temp.Labels.Severity, temp.Labels.Service, temp.Labels.Tag, temp.Annotations.URL) - } - finalData = append(finalData, temp) - - } - - jsonStr, err := json.Marshal(finalData) - - if err != nil { - log.Printf("Unable to convert JSON Data, error: %v\n", err) - } - - return jsonStr - -} - -// helper function for parsing list of alertmanager urls separated by comma -func parseURLs(urls string) []string { - var urlList []string - for _, url := range strings.Split(urls, ",") { - urlList = append(urlList, strings.Trim(url, " ")) - } - return urlList -} - -// function for get request on /api/v1/alerts alertmanager endpoint for fetching alerts. -func get(alertManagerURL string) *ssbData { - - var data *ssbData - - //GET API for fetching only GGUS alerts. - apiurl := alertManagerURL + "/api/v1/alerts?active=true&silenced=false&inhibited=false&unprocessed=false&filter=tag=\"SSB\"" - - req, err := http.NewRequest("GET", apiurl, nil) - req.Header.Add("Accept-Encoding", "identity") - req.Header.Add("Accept", "application/json") - - client := &http.Client{} - - if verbose > 1 { - dump, err := httputil.DumpRequestOut(req, true) - if err == nil { - log.Println("Request: ", string(dump)) - } - } - - resp, err := client.Do(req) - if err != nil { - panic(err) - } - defer resp.Body.Close() - - byteValue, err := io.ReadAll(resp.Body) - - if err != nil { - log.Printf("Unable to read JSON Data from AlertManager GET API, error: %v\n", err) - return data - } - - err = json.Unmarshal(byteValue, &data) - if err != nil { - log.Printf("Unable to parse JSON Data from AlertManager GET API, error: %v\n", err) - return data - } - - if verbose > 1 { - dump, err := httputil.DumpResponse(resp, true) - if err == nil { - log.Println("Response: ", string(dump)) - } - } - - return data - -} - -// function for making post request on /api/v1/alerts alertmanager endpoint for creating alerts. -func post(jsonStr []byte, alertManagerURL string) { - apiurl := alertManagerURL + "/api/v1/alerts" - - req, err := http.NewRequest("POST", apiurl, bytes.NewBuffer(jsonStr)) - req.Header.Set("Content-Type", "application/json") - - client := &http.Client{} - - if verbose > 1 { - dump, err := httputil.DumpRequestOut(req, true) - if err == nil { - log.Println("Request: ", string(dump)) - } - } - - resp, err := client.Do(req) - if err != nil { - panic(err) - } - defer resp.Body.Close() - - if verbose > 1 { - dump, err := httputil.DumpResponse(resp, true) - if err == nil { - log.Println("Response: ", string(dump)) - } - } -} - -// Function to end alerts for SSB data which had no EndTime and now they are resolved. -func deleteAlerts(alertManagerURL string) { - amData := get(alertManagerURL) - var finalData []amJSON - - for _, each := range amData.Data { - var temp amJSON - - // If SSB Data which are in Existing SSB Data Map then no need to send End Time, We Skip. - if exstSSBData[each.Annotations.SsbNumber] == 1 { - continue - } - - temp.Labels.Alertname = each.Labels.Alertname - temp.Labels.Severity = each.Labels.Severity - temp.Labels.Service = each.Labels.Service - temp.Labels.Tag = each.Labels.Tag - temp.Labels.Description = each.Labels.Description - temp.Labels.FeName = each.Labels.FeName - temp.Labels.SeName = each.Labels.SeName - temp.Labels.Type = each.Labels.Type - - temp.Annotations.Date = each.Annotations.Date - temp.Annotations.Description = each.Annotations.Description - temp.Annotations.FeName = each.Annotations.FeName - temp.Annotations.MonitState = each.Annotations.MonitState - temp.Annotations.MonitState1 = each.Annotations.MonitState1 - temp.Annotations.SeName = each.Annotations.SeName - temp.Annotations.ShortDescription = each.Annotations.ShortDescription - temp.Annotations.SsbNumber = each.Annotations.SsbNumber - temp.Annotations.SysCreatedBy = each.Annotations.SysCreatedBy - temp.Annotations.SysModCount = each.Annotations.SysModCount - temp.Annotations.SysUpdatedBy = each.Annotations.SysUpdatedBy - temp.Annotations.Type = each.Annotations.Type - temp.Annotations.UpdateTimestamp = each.Annotations.UpdateTimestamp - - temp.StartsAt = each.StartsAt - temp.EndsAt = time.Now().UTC() - - //Checking if Start Time is Afer Time Right now, maybe false alert added by mistake. **Corner Case to be handled** - if each.StartsAt.Before(temp.EndsAt) == false { - temp.StartsAt = time.Now().UTC() - temp.EndsAt = time.Now().UTC() - } - - finalData = append(finalData, temp) - } - - jsonStr, err := json.Marshal(finalData) - if err != nil { - log.Printf("Unable to convert JSON Data, error: %v\n", err) - } - - if verbose > 1 { - fmt.Println("Deleted Alerts: ", string(jsonStr)) - } - - post(jsonStr, alertManagerURL) -} - -// function containing all logics for alerting. -func alert(inp string, dryRun bool) { - - alertManagerURLList = parseURLs(alertManagerURLs) - jsonData := fetchJSON(inp) - var data ssb - data.parseJSON(jsonData) - jsonStrAM := data.convertData() //JSON data in AlertManager APIs format. - if dryRun { - fmt.Println(string(jsonStrAM)) - return - } - for _, alertManagerURL := range alertManagerURLList { - post(jsonStrAM, alertManagerURL) - deleteAlerts(alertManagerURL) - } -} - -func main() { - - var inp string - severity = "notification" // Acting as a default severity for intelligence module - tag = "monitoring" - service = "SSB" - var dryRun bool - - flag.StringVar(&inp, "input", "", "input filename") - flag.StringVar(&alertManagerURLs, "url", "", "alertmanager URLs") - flag.IntVar(&verbose, "verbose", 0, "verbosity level") - flag.BoolVar(&dryRun, "dryRun", false, "dry run mode, fetch data but do not post it to AM") - flag.Int64Var(&duration, "duration", 24, "max alert duration in hours") - flag.Parse() - - if inp == "" { - log.Fatalf("Input filename missing. Exiting....") - } - - if alertManagerURLs == "" { - log.Fatalf("AlertManager URL missing. Exiting....") - } - - if verbose > 0 { - log.SetFlags(log.LstdFlags | log.Lshortfile) - } else { - log.SetFlags(log.LstdFlags) - } - - alert(inp, dryRun) - -}