From 43510e18e2221457fd1e33ea1ac44b7a0e701bae Mon Sep 17 00:00:00 2001 From: Mac Chiang Date: Wed, 18 Dec 2019 11:54:43 +0800 Subject: [PATCH] Add slack --- cli/Makefile | 3 ++ cli/go.mod | 3 ++ cli/main.go | 4 +-- config.go | 1 + example.config.json | 3 +- example.config.yml | 7 ++-- incident.go | 32 +++++++++++++++++- slack.go | 80 +++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 126 insertions(+), 7 deletions(-) create mode 100644 cli/Makefile create mode 100644 cli/go.mod create mode 100644 slack.go diff --git a/cli/Makefile b/cli/Makefile new file mode 100644 index 0000000..caff838 --- /dev/null +++ b/cli/Makefile @@ -0,0 +1,3 @@ +build: + docker build --pull -t ${PREFIX}/$$(gcloud config get-value project 2> /dev/null)/status-monitor:$(TAG) . + diff --git a/cli/go.mod b/cli/go.mod new file mode 100644 index 0000000..98d9f66 --- /dev/null +++ b/cli/go.mod @@ -0,0 +1,3 @@ +module main + +go 1.13 diff --git a/cli/main.go b/cli/main.go index 2ac47ce..11bfc34 100644 --- a/cli/main.go +++ b/cli/main.go @@ -12,7 +12,7 @@ import ( "sync" "github.com/Sirupsen/logrus" - cachet "github.com/castawaylabs/cachet-monitor" + cachet "github.com/macchiang/cachet-monitor" docopt "github.com/docopt/docopt-go" "github.com/mitchellh/mapstructure" "gopkg.in/yaml.v2" @@ -38,7 +38,7 @@ Options: -h --help Show this screen. --version Show version --immediate Tick immediately (by default waits for first defined interval) - + Environment varaibles: CACHET_API override API url from configuration CACHET_TOKEN override API token from configuration diff --git a/config.go b/config.go index af2a05c..c573a10 100644 --- a/config.go +++ b/config.go @@ -12,6 +12,7 @@ import ( type CachetMonitor struct { SystemName string `json:"system_name" yaml:"system_name"` DateFormat string `json:"date_format" yaml:"date_format"` + SlackWebhook string `json:"slack_webhook" yaml:"slack_webhook"` API CachetAPI `json:"api"` RawMonitors []map[string]interface{} `json:"monitors" yaml:"monitors"` diff --git a/example.config.json b/example.config.json index f74c46e..6ec4bbf 100644 --- a/example.config.json +++ b/example.config.json @@ -5,6 +5,7 @@ "insecure": false }, "date_format": "02/01/2006 15:04:05 MST", + "slack_webhook": "https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX", "monitors": [ { "name": "google", @@ -56,4 +57,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/example.config.yml b/example.config.yml index 8cd05f9..e299631 100644 --- a/example.config.yml +++ b/example.config.yml @@ -6,6 +6,7 @@ api: insecure: false # https://golang.org/src/time/format.go#L57 date_format: 02/01/2006 15:04:05 MST +slack_webhook: https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX monitors: # http monitor example - name: google @@ -15,7 +16,7 @@ monitors: strict: true # HTTP method method: POST - + # set to update component (either component_id or metric_id are required) component_id: 1 # set to post lag to cachet metric (graph) @@ -28,7 +29,7 @@ monitors: message: "{{ .Monitor.Name }} check **failed** (server time: {{ .now }})\n\n{{ .FailReason }}" fixed: subject: "I HAVE BEEN FIXED" - + # seconds between checks interval: 1 # seconds for timeout @@ -62,4 +63,4 @@ monitors: - regex: [1-9] alt[1-9].aspmx.l.google.com. - exact: 10 aspmx2.googlemail.com. - exact: 1 aspmx.l.google.com. - - exact: 10 aspmx3.googlemail.com. \ No newline at end of file + - exact: 10 aspmx3.googlemail.com. diff --git a/incident.go b/incident.go index 597e84f..41e6ce2 100644 --- a/incident.go +++ b/incident.go @@ -67,7 +67,10 @@ func (incident *Incident) Send(cfg *CachetMonitor) error { if resp.StatusCode != 200 { return fmt.Errorf("Could not create/update incident!") } - + // send slack message + if cfg.SlackWebhook !="" { + sendSlack(cfg) + } return nil } @@ -110,3 +113,30 @@ func (incident *Incident) SetWatching() { func (incident *Incident) SetFixed() { incident.Status = 4 } + +// Send slack message +func (incident *Incident) sendSlack(cfg *CachetMonitor) { + color:="#bf1932" //red + if incident.ComponentStatus == 1 { + + color="#36a64f" //green + } + slack := Slack{ + WebhookUrl: cfg.SlackWebhook + Attachments: []Attachments{ + Attachments{ + Fallback: incident.Name, + Color: color, + Title: incident.Name, + TitleLink: "https://status.easyship.com", + Text: incident.Message, + Footer: "Cachet Monitor", + FooterIcon: "https://i.imgur.com/spck1w6.png", + Ts: time.Now().Unix(), + }, + }} + err := slack.SendSlackNotification() + if err != nil { + fmt.Errorf(err) + } +} diff --git a/slack.go b/slack.go new file mode 100644 index 0000000..2faef21 --- /dev/null +++ b/slack.go @@ -0,0 +1,80 @@ +package cachet + +import ( + "bytes" + "encoding/json" + "errors" + "log" + "net/http" + "time" +) + +type Slack struct { + WebhookUrl string + Attachments []Attachments `json:"attachments"` +} +type Fields struct { + Title string `json:"title"` + Value string `json:"value"` + Short bool `json:"short"` +} +type Attachments struct { + Fallback string `json:"fallback"` + Color string `json:"color"` + Pretext string `json:"pretext"` + Title string `json:"title"` + TitleLink string `json:"title_link"` + Text string `json:"text"` + Fields []Fields `json:"fields"` + ThumbURL string `json:"thumb_url"` + Footer string `json:"footer"` + FooterIcon string `json:"footer_icon"` + Ts int64 `json:"ts"` +} + +func test() { + slack := Slack{ + Attachments: []Attachments{ + Attachments{ + Fallback: "Required plain-text summary of the attachment.", + Color: "#36a64f", + Title: "Slack API Documentation", + TitleLink: "https://status.easyship.com", + Text: "Optional text that appears within the attachment", + Footer: "Cachet Monitor", + FooterIcon: "https://i.imgur.com/spck1w6.png", + Ts: time.Now().Unix(), + }, + }} + slack.WebhookUrl = "https://hooks.slack.com/services/0000000/00000000/xxxxxxxxxxxxxxxxxxx" + err := slack.SendSlackNotification() + if err != nil { + log.Fatal(err) + } +} + +// SendSlackNotification will post to an 'Incoming Webook' url setup in Slack Apps. It accepts +// some text and the slack channel is saved within Slack. +func (slack *Slack) SendSlackNotification() error { + + slackBody, _ := json.Marshal(slack) + req, err := http.NewRequest(http.MethodPost, slack.WebhookUrl, bytes.NewBuffer(slackBody)) + if err != nil { + return err + } + + req.Header.Add("Content-Type", "application/json") + + client := &http.Client{Timeout: 10 * time.Second} + resp, err := client.Do(req) + if err != nil { + return err + } + + buf := new(bytes.Buffer) + buf.ReadFrom(resp.Body) + if buf.String() != "ok" { + return errors.New("Non-ok response returned from Slack") + } + return nil +}