mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
* Use secrets service in pluginproxy
* Use secrets service in pluginxontext
* Use secrets service in pluginsettings
* Use secrets service in provisioning
* Use secrets service in authinfoservice
* Use secrets service in api
* Use secrets service in sqlstore
* Use secrets service in dashboardshapshots
* Use secrets service in tsdb
* Use secrets service in datasources
* Use secrets service in alerting
* Use secrets service in ngalert
* Break cyclic dependancy
* Refactor service
* Break cyclic dependancy
* Add FakeSecretsStore
* Setup Secrets Service in sqlstore
* Fix
* Continue secrets service refactoring
* Fix cyclic dependancy in sqlstore tests
* Fix secrets service references
* Fix linter errors
* Add fake secrets service for tests
* Refactor SetupTestSecretsService
* Update setting up secret service in tests
* Fix missing secrets service in multiorg_alertmanager_test
* Use fake db in tests and sort imports
* Use fake db in datasources tests
* Fix more tests
* Fix linter issues
* Attempt to fix plugin proxy tests
* Pass secrets service to getPluginProxiedRequest in pluginproxy tests
* Fix pluginproxy tests
* Revert using secrets service in alerting and provisioning
* Update decryptFn in alerting migration
* Rename defaultProvider to currentProvider
* Use fake secrets service in alert channels tests
* Refactor secrets service test helper
* Update setting up secrets service in tests
* Revert alerting changes in api
* Add comments
* Remove secrets service from background services
* Convert global encryption functions into vars
* Revert "Convert global encryption functions into vars"
This reverts commit 498eb19859.
* Add feature toggle for envelope encryption
* Rename toggle
Co-authored-by: Emil Tullstedt <emil.tullstedt@grafana.com>
Co-authored-by: Joan López de la Franca Beltran <joanjan14@gmail.com>
158 lines
4.2 KiB
Go
158 lines
4.2 KiB
Go
package channels
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/grafana/grafana/pkg/bus"
|
|
"github.com/grafana/grafana/pkg/infra/log"
|
|
"github.com/grafana/grafana/pkg/models"
|
|
"github.com/prometheus/alertmanager/template"
|
|
"github.com/prometheus/alertmanager/types"
|
|
"github.com/prometheus/common/model"
|
|
)
|
|
|
|
type SensuGoNotifier struct {
|
|
*Base
|
|
log log.Logger
|
|
tmpl *template.Template
|
|
|
|
URL string
|
|
Entity string
|
|
Check string
|
|
Namespace string
|
|
Handler string
|
|
APIKey string
|
|
Message string
|
|
}
|
|
|
|
// NewSensuGoNotifier is the constructor for the SensuGo notifier
|
|
func NewSensuGoNotifier(model *NotificationChannelConfig, t *template.Template, fn GetDecryptedValueFn) (*SensuGoNotifier, error) {
|
|
if model.Settings == nil {
|
|
return nil, receiverInitError{Cfg: *model, Reason: "no settings supplied"}
|
|
}
|
|
|
|
url := model.Settings.Get("url").MustString()
|
|
if url == "" {
|
|
return nil, receiverInitError{Cfg: *model, Reason: "could not find URL property in settings"}
|
|
}
|
|
|
|
apikey := fn(context.Background(), model.SecureSettings, "apikey", model.Settings.Get("apikey").MustString())
|
|
if apikey == "" {
|
|
return nil, receiverInitError{Cfg: *model, Reason: "could not find the API key property in settings"}
|
|
}
|
|
|
|
return &SensuGoNotifier{
|
|
Base: NewBase(&models.AlertNotification{
|
|
Uid: model.UID,
|
|
Name: model.Name,
|
|
Type: model.Type,
|
|
DisableResolveMessage: model.DisableResolveMessage,
|
|
Settings: model.Settings,
|
|
SecureSettings: model.SecureSettings,
|
|
}),
|
|
URL: url,
|
|
Entity: model.Settings.Get("entity").MustString(),
|
|
Check: model.Settings.Get("check").MustString(),
|
|
Namespace: model.Settings.Get("namespace").MustString(),
|
|
Handler: model.Settings.Get("handler").MustString(),
|
|
APIKey: apikey,
|
|
Message: model.Settings.Get("message").MustString(`{{ template "default.message" .}}`),
|
|
log: log.New("alerting.notifier.sensugo"),
|
|
tmpl: t,
|
|
}, nil
|
|
}
|
|
|
|
// Notify sends an alert notification to Sensu Go
|
|
func (sn *SensuGoNotifier) Notify(ctx context.Context, as ...*types.Alert) (bool, error) {
|
|
sn.log.Debug("Sending Sensu Go result")
|
|
|
|
var tmplErr error
|
|
tmpl, _ := TmplText(ctx, sn.tmpl, as, sn.log, &tmplErr)
|
|
|
|
// Sensu Go alerts require an entity and a check. We set it to the user-specified
|
|
// value (optional), else we fallback and use the grafana rule anme and ruleID.
|
|
entity := tmpl(sn.Entity)
|
|
if entity == "" {
|
|
entity = "default"
|
|
}
|
|
|
|
check := tmpl(sn.Check)
|
|
if check == "" {
|
|
check = "default"
|
|
}
|
|
|
|
alerts := types.Alerts(as...)
|
|
status := 0
|
|
if alerts.Status() == model.AlertFiring {
|
|
// TODO figure out about NoData old state (we used to send status 1 in that case)
|
|
status = 2
|
|
}
|
|
|
|
namespace := tmpl(sn.Namespace)
|
|
if namespace == "" {
|
|
namespace = "default"
|
|
}
|
|
|
|
var handlers []string
|
|
if sn.Handler != "" {
|
|
handlers = []string{tmpl(sn.Handler)}
|
|
}
|
|
|
|
ruleURL := joinUrlPath(sn.tmpl.ExternalURL.String(), "/alerting/list", sn.log)
|
|
bodyMsgType := map[string]interface{}{
|
|
"entity": map[string]interface{}{
|
|
"metadata": map[string]interface{}{
|
|
"name": entity,
|
|
"namespace": namespace,
|
|
},
|
|
},
|
|
"check": map[string]interface{}{
|
|
"metadata": map[string]interface{}{
|
|
"name": check,
|
|
"labels": map[string]string{
|
|
"ruleURL": ruleURL,
|
|
},
|
|
},
|
|
"output": tmpl(sn.Message),
|
|
"issued": time.Now().Unix(),
|
|
"interval": 86400,
|
|
"status": status,
|
|
"handlers": handlers,
|
|
},
|
|
"ruleUrl": ruleURL,
|
|
}
|
|
|
|
if tmplErr != nil {
|
|
sn.log.Debug("failed to template sensugo message", "err", tmplErr.Error())
|
|
}
|
|
|
|
body, err := json.Marshal(bodyMsgType)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
cmd := &models.SendWebhookSync{
|
|
Url: fmt.Sprintf("%s/api/core/v2/namespaces/%s/events", strings.TrimSuffix(sn.URL, "/"), namespace),
|
|
Body: string(body),
|
|
HttpMethod: "POST",
|
|
HttpHeader: map[string]string{
|
|
"Content-Type": "application/json",
|
|
"Authorization": fmt.Sprintf("Key %s", sn.APIKey),
|
|
},
|
|
}
|
|
if err := bus.DispatchCtx(ctx, cmd); err != nil {
|
|
sn.log.Error("Failed to send Sensu Go event", "error", err, "sensugo", sn.Name)
|
|
return false, err
|
|
}
|
|
|
|
return true, nil
|
|
}
|
|
|
|
func (sn *SensuGoNotifier) SendResolved() bool {
|
|
return !sn.GetDisableResolveMessage()
|
|
}
|