Files
karma/main.go
Łukasz Mierzwa b6dd993c2b Add support for proxying user connection to Alertmanager
Fixes #190.

With this feature unsee can be configured to proxy requests to selected Alertmanager instances, if it's enabled unsee silence form will send a request via unsee rather than directly. This allows users to manage silences in environments where they have access to unsee but not to Alertmanager. Only silences endpoints on Alertmanager API are proxied.
2018-01-03 16:17:58 -08:00

164 lines
4.1 KiB
Go

package main
import (
"fmt"
"html/template"
"path"
"strings"
"time"
"github.com/cloudflare/unsee/internal/alertmanager"
"github.com/cloudflare/unsee/internal/config"
"github.com/cloudflare/unsee/internal/models"
"github.com/cloudflare/unsee/internal/transform"
"github.com/DeanThompson/ginpprof"
"github.com/gin-contrib/gzip"
"github.com/gin-contrib/static"
"github.com/gin-gonic/contrib/sentry"
"github.com/gin-gonic/gin"
"github.com/patrickmn/go-cache"
raven "github.com/getsentry/raven-go"
ginprometheus "github.com/mcuadros/go-gin-prometheus"
log "github.com/sirupsen/logrus"
)
var (
version = "dev"
// ticker is a timer used by background loop that will keep pulling
// data from Alertmanager
ticker *time.Ticker
// apiCache will be used to keep short lived copy of JSON reponses generated for the UI
// If there are requests with the same filter we should respond from cache
// rather than do all the filtering every time
apiCache *cache.Cache
)
func getViewURL(sub string) string {
u := path.Join(config.Config.Listen.Prefix, sub)
if strings.HasSuffix(sub, "/") {
// if sub path had trailing slash then add it here, since path.Join will
// skip it
return u + "/"
}
return u
}
func setupRouter(router *gin.Engine) {
router.Use(gzip.Gzip(gzip.DefaultCompression))
router.Use(static.Serve(getViewURL("/static"), newBinaryFileSystem("static")))
router.GET(getViewURL("/favicon.ico"), favicon)
router.GET(getViewURL("/"), index)
router.GET(getViewURL("/help"), help)
router.GET(getViewURL("/alerts.json"), alerts)
router.GET(getViewURL("/autocomplete.json"), autocomplete)
}
func setupUpstreams() {
for _, s := range config.Config.Alertmanager.Servers {
err := alertmanager.NewAlertmanager(s.Name, s.URI, s.Timeout, s.Proxy)
if err != nil {
log.Fatalf("Failed to configure Alertmanager '%s' with URI '%s': %s", s.Name, s.URI, err)
}
}
}
func setupLogger() {
switch config.Config.Log.Level {
case "debug":
log.SetLevel(log.DebugLevel)
case "info":
log.SetLevel(log.InfoLevel)
case "warning":
log.SetLevel(log.WarnLevel)
case "error":
log.SetLevel(log.ErrorLevel)
case "fatal":
log.SetLevel(log.FatalLevel)
case "panic":
log.SetLevel(log.PanicLevel)
default:
log.Fatalf("Unknown log level '%s'", config.Config.Log.Level)
}
}
func main() {
config.Config.Read()
setupLogger()
// timer duration cannot be zero second or a negative one
if config.Config.Alertmanager.Interval <= time.Second*0 {
log.Fatalf("Invalid AlertmanagerTTL value '%v'", config.Config.Alertmanager.Interval)
}
log.Infof("Version: %s", version)
if config.Config.Log.Config {
config.Config.LogValues()
}
jiraRules := []models.JiraRule{}
for _, rule := range config.Config.JIRA {
jiraRules = append(jiraRules, models.JiraRule{Regex: rule.Regex, URI: rule.URI})
}
transform.ParseRules(jiraRules)
apiCache = cache.New(cache.NoExpiration, 10*time.Second)
setupUpstreams()
if len(alertmanager.GetAlertmanagers()) == 0 {
log.Fatal("No valid Alertmanager URIs defined")
}
// before we start try to fetch data from Alertmanager
log.Info("Initial Alertmanager query")
pullFromAlertmanager()
log.Info("Done, starting HTTP server")
// background loop that will fetch updates from Alertmanager
ticker = time.NewTicker(config.Config.Alertmanager.Interval)
go Tick()
switch config.Config.Debug {
case true:
gin.SetMode(gin.DebugMode)
case false:
gin.SetMode(gin.ReleaseMode)
}
router := gin.New()
var t *template.Template
t = loadTemplates(t, "templates")
t = loadTemplates(t, "static/dist/templates")
router.SetHTMLTemplate(t)
prom := ginprometheus.NewPrometheus("gin")
prom.MetricsPath = getViewURL("/metrics")
prom.Use(router)
if config.Config.Debug {
ginpprof.Wrapper(router)
}
if config.Config.Sentry.Public != "" {
raven.SetRelease(version)
router.Use(sentry.Recovery(raven.DefaultClient, false))
}
setupRouter(router)
for _, am := range alertmanager.GetAlertmanagers() {
setupRouterProxyHandlers(router, am)
}
listen := fmt.Sprintf("%s:%d", config.Config.Listen.Address, config.Config.Listen.Port)
log.Infof("Listening on %s", listen)
err := router.Run(listen)
if err != nil {
log.Fatal(err)
}
}