From 43510e18e2221457fd1e33ea1ac44b7a0e701bae Mon Sep 17 00:00:00 2001 From: Mac Chiang Date: Wed, 18 Dec 2019 11:54:43 +0800 Subject: [PATCH 1/2] 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 +} From f9f5c278ec1b05178eea10c1bde03da6ba3932bd Mon Sep 17 00:00:00 2001 From: Mac Chiang Date: Wed, 18 Dec 2019 12:35:44 +0800 Subject: [PATCH 2/2] add test --- cli/Dockerfile | 12 ++++++++++++ cli/Makefile | 2 +- cli/go.mod | 9 +++++++++ cli/go.sum | 20 ++++++++++++++++++++ cli/main.go | 2 +- monitor.go | 2 +- 6 files changed, 44 insertions(+), 3 deletions(-) create mode 100644 cli/Dockerfile create mode 100644 cli/go.sum diff --git a/cli/Dockerfile b/cli/Dockerfile new file mode 100644 index 0000000..7fa15ca --- /dev/null +++ b/cli/Dockerfile @@ -0,0 +1,12 @@ +# build stage +FROM golang:alpine AS build-env +RUN set -eux; \ + apk add --no-cache --virtual .build-deps \ + git gcc libc-dev; +ENV GO111MODULE on +WORKDIR /go/main +ADD go.mod go.sum ./ +RUN go mod download +# WORKDIR /go/src/status-monitor +ADD main.go ./ +RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -a -installsuffix cgo -o main main.go diff --git a/cli/Makefile b/cli/Makefile index caff838..8d9ae53 100644 --- a/cli/Makefile +++ b/cli/Makefile @@ -1,3 +1,3 @@ build: - docker build --pull -t ${PREFIX}/$$(gcloud config get-value project 2> /dev/null)/status-monitor:$(TAG) . + docker build . diff --git a/cli/go.mod b/cli/go.mod index 98d9f66..759b6a6 100644 --- a/cli/go.mod +++ b/cli/go.mod @@ -1,3 +1,12 @@ module main go 1.13 + +require ( + github.com/castawaylabs/cachet-monitor v1.1.0 // indirect + github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815 // indirect + github.com/macchiang/cachet-monitor v1.1.0 // indirect + github.com/mitchellh/mapstructure v1.1.2 // indirect + github.com/sirupsen/logrus v1.4.2 // indirect + gopkg.in/yaml.v2 v2.2.7 // indirect +) diff --git a/cli/go.sum b/cli/go.sum new file mode 100644 index 0000000..32482f1 --- /dev/null +++ b/cli/go.sum @@ -0,0 +1,20 @@ +github.com/castawaylabs/cachet-monitor v1.1.0 h1:T8NshhwHjEIbdlWkeRBuYdnU2ktpBnZpwgh6nxrp62w= +github.com/castawaylabs/cachet-monitor v1.1.0/go.mod h1:FBK1+4+fLd80wd/+U4Zy8YshPlpgWEvup79AoapOZ2E= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815 h1:bWDMxwH3px2JBh6AyO7hdCn/PkvCZXii8TGj7sbtEbQ= +github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/macchiang/cachet-monitor v1.1.0 h1:um5ymKBF11Dau8yKCAg82HS6F/og0tODiIOLOdwnnzc= +github.com/macchiang/cachet-monitor v1.1.0/go.mod h1:cNiyqtsa4pEzPn0v2tlf6oejVg4mfUts2qNaxFnCDeE= +github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo= +gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/cli/main.go b/cli/main.go index 11bfc34..cac33dd 100644 --- a/cli/main.go +++ b/cli/main.go @@ -11,7 +11,7 @@ import ( "strings" "sync" - "github.com/Sirupsen/logrus" + "github.com/sirupsen/logrus" cachet "github.com/macchiang/cachet-monitor" docopt "github.com/docopt/docopt-go" "github.com/mitchellh/mapstructure" diff --git a/monitor.go b/monitor.go index f7cbba6..d90e090 100644 --- a/monitor.go +++ b/monitor.go @@ -4,7 +4,7 @@ import ( "sync" "time" - "github.com/Sirupsen/logrus" + "github.com/sirupsen/logrus" ) const DefaultInterval = time.Second * 60