add grafana support

This commit is contained in:
Martin/Geno 2019-02-13 04:32:06 +01:00
parent c650f280f5
commit caf0dfe497
No known key found for this signature in database
GPG Key ID: 9D7D3C6BFF600C6A
5 changed files with 165 additions and 50 deletions

View File

@ -6,51 +6,62 @@ import (
"net/http" "net/http"
"github.com/bdlm/log" "github.com/bdlm/log"
"github.com/mitchellh/mapstructure"
libHTTP "github.com/genofire/golang-lib/http" libHTTP "github.com/genofire/golang-lib/http"
xmpp "github.com/mattn/go-xmpp" xmpp "github.com/mattn/go-xmpp"
"dev.sum7.eu/genofire/hook2xmpp/runtime" "dev.sum7.eu/genofire/hook2xmpp/runtime"
) )
const hookType = "git" const hookType = "circleci"
type requestBody struct {
Payload struct {
VCSURL string `mapstructure:"vcs_url"`
Status string `mapstructure:"status"`
BuildNum float64 `mapstructure:"build_num"`
BuildURL string `mapstructure:"build_url"`
BuildTime float64 `mapstructure:"build_time_millis"`
Subject string `mapstructure:"subject"`
} `mapstructure:"payload"`
}
func (r requestBody) String() string {
return fmt.Sprintf("#%0.f (%0.fs): %s", r.Payload.BuildNum, r.Payload.BuildTime/1000, r.Payload.Subject)
}
func init() { func init() {
runtime.HookRegister[hookType] = func(client *xmpp.Client, hooks []runtime.Hook) func(w http.ResponseWriter, r *http.Request) { runtime.HookRegister[hookType] = func(client *xmpp.Client, hooks []runtime.Hook) func(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
logger := log.WithField("type", hookType) logger := log.WithField("type", hookType)
var body map[string]interface{} var body interface{}
libHTTP.Read(r, &body) libHTTP.Read(r, &body)
payload := body["payload"].(map[string]interface{}) var request requestBody
url, ok := payload["vcs_url"].(string) if err := mapstructure.Decode(body, &request); err != nil {
if !ok { logger.Errorf("no readable payload: %s", err)
logger.Error("no readable payload")
http.Error(w, fmt.Sprintf("no readable payload"), http.StatusInternalServerError) http.Error(w, fmt.Sprintf("no readable payload"), http.StatusInternalServerError)
return return
} }
logger = logger.WithField("url", url) logger = logger.WithFields(map[string]interface{}{
"url": request.Payload.VCSURL,
"msg": request.String(),
})
status := payload["status"].(string) ok := false
buildNum := payload["build_num"].(float64)
buildURL := payload["build_url"].(string)
buildTime := payload["build_time_millis"].(float64)
subject := payload["subject"].(string)
msg := fmt.Sprintf("[%s] %s (%0.fs) - #%0.f: %s \n%s", url, status, buildTime/1000, buildNum, subject, buildURL)
logger = logger.WithField("msg", msg)
ok = false
for _, hook := range hooks { for _, hook := range hooks {
if url != hook.URL { if request.Payload.VCSURL != hook.URL {
continue continue
} }
logger.Infof("run hook") logger.Infof("run hook")
runtime.Notify(client, hook, msg) runtime.Notify(client, hook, request.String())
ok = true ok = true
} }
if !ok { if !ok {
logger.Warnf("no hook found") logger.Warnf("no hook found")
http.Error(w, fmt.Sprintf("no configuration for circleci for url: %s", url), http.StatusNotFound) http.Error(w, fmt.Sprintf("no configuration for %s for url: %s", hookType, request.Payload.VCSURL), http.StatusNotFound)
} }
} }
} }

View File

@ -1 +0,0 @@
package circleci

View File

@ -6,6 +6,7 @@ import (
"net/http" "net/http"
"github.com/bdlm/log" "github.com/bdlm/log"
"github.com/mitchellh/mapstructure"
libHTTP "github.com/genofire/golang-lib/http" libHTTP "github.com/genofire/golang-lib/http"
xmpp "github.com/mattn/go-xmpp" xmpp "github.com/mattn/go-xmpp"
@ -37,30 +38,29 @@ func init() {
var body map[string]interface{} var body map[string]interface{}
libHTTP.Read(r, &body) libHTTP.Read(r, &body)
repository := body["repository"].(map[string]interface{}) var request requestBody
url, ok := repository["html_url"].(string) if err := mapstructure.Decode(body, &request); err != nil {
if !ok { logger.Errorf("no readable payload: %s", err)
logger.Error("no readable payload")
http.Error(w, fmt.Sprintf("no readable payload"), http.StatusInternalServerError) http.Error(w, fmt.Sprintf("no readable payload"), http.StatusInternalServerError)
return return
} }
logger = logger.WithField("url", url) logger = logger.WithFields(map[string]interface{}{
"url": request.Repository.HTMLURL,
"msg": request.String(event),
})
msg := PayloadToString(event, body) ok := false
logger = logger.WithField("msg", msg)
ok = false
for _, hook := range hooks { for _, hook := range hooks {
if url != hook.URL { if request.Repository.HTMLURL != hook.URL {
continue continue
} }
logger.Infof("run hook") logger.Infof("run hook")
runtime.Notify(client, hook, msg) runtime.Notify(client, hook, request.String(event))
ok = true ok = true
} }
if !ok { if !ok {
logger.Warnf("no hook found") logger.Warnf("no hook found")
http.Error(w, fmt.Sprintf("no configuration for git for url: %s", url), http.StatusNotFound) http.Error(w, fmt.Sprintf("no configuration for %s for url: %s", hookType, request.Repository.HTMLURL), http.StatusNotFound)
} }
} }
} }

View File

@ -49,38 +49,57 @@ var eventMsg = map[string]string{
"gollum_edited": "Wiki: edited page", "gollum_edited": "Wiki: edited page",
} }
func PayloadToString(event string, payloadOrigin interface{}) string {
payload := payloadOrigin.(map[string]interface{})
repository := payload["repository"].(map[string]interface{}) type requestBody struct {
repoName := repository["full_name"].(string) Repository struct {
HTMLURL string `mapstructure:"html_url"`
FullName string `mapstructure:"full_name"`
} `mapstructure:"repository"`
//push
Pusher struct {
Name string `mapstructure:"name"`
} `mapstructure:"pusher"`
Commits []struct {
Added []interface{} `mapstructure:"added"`
Removed []interface{} `mapstructure:"removed"`
Modified []interface{} `mapstructure:"modified"`
} `mapstructure:"commits"`
Compare string `mapstructure:"compare"`
Ref string `mapstructure:"ref"`
// issue + fallback
Sender struct {
Login string `mapstructure:"login"`
} `mapstructure:"sender"`
// issue
Action string `mapstructure:"action"`
Issue struct {
HTMLURL string `mapstructure:"html_url"`
Number float64 `mapstructure:"number"`
Title string `mapstructure:"title"`
} `mapstructure:"issue"`
}
msg := fmt.Sprintf("[%s]", repoName) func (r requestBody) String(event string) string {
msg := fmt.Sprintf("[%s]", r.Repository.FullName)
if event == "push" { if event == "push" {
pusher := payload["pusher"].(map[string]interface{})
commits := payload["commits"].([]interface{})
added := 0 added := 0
removed := 0 removed := 0
modified := 0 modified := 0
for _, commitOrigin := range commits { for _, commit := range r.Commits {
commit := commitOrigin.(map[string]interface{}) added += len(commit.Added)
added += len(commit["added"].([]interface{})) removed += len(commit.Removed)
removed += len(commit["removed"].([]interface{})) modified += len(commit.Modified)
modified += len(commit["modified"].([]interface{}))
} }
msg = fmt.Sprintf("%s %s - pushed %d commit(s) to %s [+%d/-%d/\u00B1%d] \n %s", msg, pusher["name"], len(commits), strings.TrimLeft(payload["ref"].(string), "refs/heads/"), added, removed, modified, payload["compare"]) msg = fmt.Sprintf("%s %s - pushed %d commit(s) to %s [+%d/-%d/\u00B1%d]: %s", msg, r.Pusher.Name, len(r.Commits), strings.TrimLeft(r.Ref, "refs/heads/"), added, removed, modified, r.Compare)
} else if event == "issues" || event == "issue_comment" { } else if event == "issues" || event == "issue_comment" {
sender := payload["sender"].(map[string]interface{}) msg = fmt.Sprintf("%s %s - %s action #%.0f: %s - %s", msg, r.Sender.Login, r.Action, r.Issue.Number, r.Issue.Title, r.Issue.HTMLURL)
issue := payload["issue"].(map[string]interface{})
msg = fmt.Sprintf("%s %s - %s action #%.0f: %s \n %s", msg, sender["login"], payload["action"], issue["number"], issue["title"], issue["html_url"])
} else { } else {
sender := payload["sender"].(map[string]interface{})
text := eventMsg[event] text := eventMsg[event]
if text == "" { if text == "" {
text = event text = event
} }
msg = fmt.Sprintf("%s %s - %s", msg, sender["login"], text) msg = fmt.Sprintf("%s %s - %s", msg, r.Sender.Login, text)
} }
return msg return msg
} }

86
grafana/main.go Normal file
View File

@ -0,0 +1,86 @@
package circleci
import (
"fmt"
"net/url"
"net/http"
"github.com/bdlm/log"
"github.com/mitchellh/mapstructure"
libHTTP "github.com/genofire/golang-lib/http"
xmpp "github.com/mattn/go-xmpp"
"dev.sum7.eu/genofire/hook2xmpp/runtime"
)
const hookType = "grafana"
type evalMatch struct {
Tags map[string]string `mapstructure:"tags,omitempty"`
Metric string `mapstructure:"metric"`
Value float64 `mapstructure:"value"`
}
type requestBody struct {
Title string `mapstructure:"title"`
State string `mapstructure:"state"`
RuleID int64 `mapstructure:"ruleId"`
RuleName string `mapstructure:"ruleName"`
RuleURL string `mapstructure:"ruleUrl"`
EvalMatches []evalMatch `mapstructure:"evalMatches"`
ImageURL string `mapstructure:"imageUrl"`
Message string `mapstructure:"message"`
}
func (r requestBody) String() string {
msg := fmt.Sprintf("%s: %s", r.Title, r.Message)
for _, e := range r.EvalMatches {
msg = fmt.Sprintf("%s %s=%d", msg, e.Metric, e.Value)
}
return msg
}
func init() {
runtime.HookRegister[hookType] = func(client *xmpp.Client, hooks []runtime.Hook) func(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
logger := log.WithField("type", hookType)
var body interface{}
libHTTP.Read(r, &body)
var request requestBody
if err := mapstructure.Decode(body, &request); err != nil {
logger.Errorf("no readable payload: %s", err)
http.Error(w, fmt.Sprintf("no readable payload"), http.StatusInternalServerError)
return
}
logger = logger.WithFields(map[string]interface{}{
"url": request.RuleURL,
"msg": request.String(),
})
ruleURL, err := url.Parse(request.RuleURL)
if err != nil {
logger.Errorf("could not parse ruleURL: %s", err)
http.Error(w, fmt.Sprintf("no readable payload"), http.StatusInternalServerError)
return
}
ok := false
for _, hook := range hooks {
if ruleURL.Hostname() != hook.URL {
continue
}
logger.Infof("run hook")
runtime.Notify(client, hook, request.String())
runtime.NotifyImage(client, hook, request.ImageURL)
ok = true
}
if !ok {
logger.Warnf("no hook found")
http.Error(w, fmt.Sprintf("no configuration for %s for url: %s", hookType, request.RuleURL), http.StatusNotFound)
}
}
}
}