mirror of
https://github.com/grafana/grafana.git
synced 2025-02-10 23:55:47 -06:00
Alerting: use alerting GrafanaReceiver and BuildReceiverConfiguration in Grafana (#65224)
* replace receiver errors with one from alerting * add the converter to alerting models * update buildReceiverIntegration to accept GrafanaReceiver --------- Co-authored-by: George Robinson <george.robinson@grafana.com>
This commit is contained in:
parent
e5e0a1cbbf
commit
afd52d0866
@ -406,7 +406,7 @@ func statusForTestReceivers(v []notifier.TestReceiverResult) int {
|
|||||||
for _, next := range receiver.Configs {
|
for _, next := range receiver.Configs {
|
||||||
if next.Error != nil {
|
if next.Error != nil {
|
||||||
var (
|
var (
|
||||||
invalidReceiverErr notifier.InvalidReceiverError
|
invalidReceiverErr alertingNotify.InvalidReceiverError
|
||||||
receiverTimeoutErr alertingNotify.ReceiverTimeoutError
|
receiverTimeoutErr alertingNotify.ReceiverTimeoutError
|
||||||
)
|
)
|
||||||
if errors.As(next.Error, &invalidReceiverErr) {
|
if errors.As(next.Error, &invalidReceiverErr) {
|
||||||
|
@ -108,7 +108,7 @@ func TestStatusForTestReceivers(t *testing.T) {
|
|||||||
Name: "test1",
|
Name: "test1",
|
||||||
UID: "uid1",
|
UID: "uid1",
|
||||||
Status: "failed",
|
Status: "failed",
|
||||||
Error: notifier.InvalidReceiverError{},
|
Error: alertingNotify.InvalidReceiverError{},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
Name: "test2",
|
Name: "test2",
|
||||||
@ -116,7 +116,7 @@ func TestStatusForTestReceivers(t *testing.T) {
|
|||||||
Name: "test2",
|
Name: "test2",
|
||||||
UID: "uid2",
|
UID: "uid2",
|
||||||
Status: "failed",
|
Status: "failed",
|
||||||
Error: notifier.InvalidReceiverError{},
|
Error: alertingNotify.InvalidReceiverError{},
|
||||||
}},
|
}},
|
||||||
}}))
|
}}))
|
||||||
})
|
})
|
||||||
@ -148,7 +148,7 @@ func TestStatusForTestReceivers(t *testing.T) {
|
|||||||
Name: "test1",
|
Name: "test1",
|
||||||
UID: "uid1",
|
UID: "uid1",
|
||||||
Status: "failed",
|
Status: "failed",
|
||||||
Error: notifier.InvalidReceiverError{},
|
Error: alertingNotify.InvalidReceiverError{},
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
Name: "test2",
|
Name: "test2",
|
||||||
@ -156,7 +156,7 @@ func TestStatusForTestReceivers(t *testing.T) {
|
|||||||
Name: "test2",
|
Name: "test2",
|
||||||
UID: "uid2",
|
UID: "uid2",
|
||||||
Status: "failed",
|
Status: "failed",
|
||||||
Error: notifier.ReceiverTimeoutError{},
|
Error: alertingNotify.ReceiverTimeoutError{},
|
||||||
}},
|
}},
|
||||||
}}))
|
}}))
|
||||||
})
|
})
|
||||||
|
@ -334,7 +334,7 @@ func (am *Alertmanager) buildIntegrationsMap(receivers []*apimodels.PostableApiR
|
|||||||
func (am *Alertmanager) buildReceiverIntegrations(receiver *apimodels.PostableApiReceiver, tmpl *alertingNotify.Template) ([]*alertingNotify.Integration, error) {
|
func (am *Alertmanager) buildReceiverIntegrations(receiver *apimodels.PostableApiReceiver, tmpl *alertingNotify.Template) ([]*alertingNotify.Integration, error) {
|
||||||
integrations := make([]*alertingNotify.Integration, 0, len(receiver.GrafanaManagedReceivers))
|
integrations := make([]*alertingNotify.Integration, 0, len(receiver.GrafanaManagedReceivers))
|
||||||
for i, r := range receiver.GrafanaManagedReceivers {
|
for i, r := range receiver.GrafanaManagedReceivers {
|
||||||
n, err := am.buildReceiverIntegration(r, tmpl)
|
n, err := am.buildReceiverIntegration(PostableGrafanaReceiverToGrafanaReceiver(r), tmpl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -343,14 +343,14 @@ func (am *Alertmanager) buildReceiverIntegrations(receiver *apimodels.PostableAp
|
|||||||
return integrations, nil
|
return integrations, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (am *Alertmanager) buildReceiverIntegration(r *apimodels.PostableGrafanaReceiver, tmpl *alertingNotify.Template) (alertingNotify.NotificationChannel, error) {
|
func (am *Alertmanager) buildReceiverIntegration(r *alertingNotify.GrafanaReceiver, tmpl *alertingNotify.Template) (alertingNotify.NotificationChannel, error) {
|
||||||
// secure settings are already encrypted at this point
|
// secure settings are already encrypted at this point
|
||||||
secureSettings := make(map[string][]byte, len(r.SecureSettings))
|
secureSettings := make(map[string][]byte, len(r.SecureSettings))
|
||||||
|
|
||||||
for k, v := range r.SecureSettings {
|
for k, v := range r.SecureSettings {
|
||||||
d, err := base64.StdEncoding.DecodeString(v)
|
d, err := base64.StdEncoding.DecodeString(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, InvalidReceiverError{
|
return nil, alertingNotify.InvalidReceiverError{
|
||||||
Receiver: r,
|
Receiver: r,
|
||||||
Err: errors.New("failed to decode secure setting"),
|
Err: errors.New("failed to decode secure setting"),
|
||||||
}
|
}
|
||||||
@ -365,27 +365,27 @@ func (am *Alertmanager) buildReceiverIntegration(r *apimodels.PostableGrafanaRec
|
|||||||
Name: r.Name,
|
Name: r.Name,
|
||||||
Type: r.Type,
|
Type: r.Type,
|
||||||
DisableResolveMessage: r.DisableResolveMessage,
|
DisableResolveMessage: r.DisableResolveMessage,
|
||||||
Settings: json.RawMessage(r.Settings),
|
Settings: r.Settings,
|
||||||
SecureSettings: secureSettings,
|
SecureSettings: secureSettings,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
factoryConfig, err := receivers.NewFactoryConfig(cfg, NewNotificationSender(am.NotificationService), am.decryptFn, tmpl, newImageStore(am.Store), LoggerFactory, setting.BuildVersion)
|
factoryConfig, err := receivers.NewFactoryConfig(cfg, NewNotificationSender(am.NotificationService), am.decryptFn, tmpl, newImageStore(am.Store), LoggerFactory, setting.BuildVersion)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, InvalidReceiverError{
|
return nil, alertingNotify.InvalidReceiverError{
|
||||||
Receiver: r,
|
Receiver: r,
|
||||||
Err: err,
|
Err: err,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
receiverFactory, exists := alertingNotify.Factory(r.Type)
|
receiverFactory, exists := alertingNotify.Factory(r.Type)
|
||||||
if !exists {
|
if !exists {
|
||||||
return nil, InvalidReceiverError{
|
return nil, alertingNotify.InvalidReceiverError{
|
||||||
Receiver: r,
|
Receiver: r,
|
||||||
Err: fmt.Errorf("notifier %s is not supported", r.Type),
|
Err: fmt.Errorf("notifier %s is not supported", r.Type),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
n, err := receiverFactory(factoryConfig)
|
n, err := receiverFactory(factoryConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, InvalidReceiverError{
|
return nil, alertingNotify.InvalidReceiverError{
|
||||||
Receiver: r,
|
Receiver: r,
|
||||||
Err: err,
|
Err: err,
|
||||||
}
|
}
|
||||||
|
42
pkg/services/ngalert/notifier/compat.go
Normal file
42
pkg/services/ngalert/notifier/compat.go
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
package notifier
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
alertingNotify "github.com/grafana/alerting/notify"
|
||||||
|
|
||||||
|
apimodels "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
|
||||||
|
)
|
||||||
|
|
||||||
|
func PostableGrafanaReceiverToGrafanaReceiver(p *apimodels.PostableGrafanaReceiver) *alertingNotify.GrafanaReceiver {
|
||||||
|
return &alertingNotify.GrafanaReceiver{
|
||||||
|
UID: p.UID,
|
||||||
|
Name: p.Name,
|
||||||
|
Type: p.Type,
|
||||||
|
DisableResolveMessage: p.DisableResolveMessage,
|
||||||
|
Settings: json.RawMessage(p.Settings),
|
||||||
|
SecureSettings: p.SecureSettings,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func PostableApiReceiverToApiReceiver(r *apimodels.PostableApiReceiver) *alertingNotify.APIReceiver {
|
||||||
|
receivers := alertingNotify.GrafanaReceivers{
|
||||||
|
Receivers: make([]*alertingNotify.GrafanaReceiver, 0, len(r.GrafanaManagedReceivers)),
|
||||||
|
}
|
||||||
|
for _, receiver := range r.GrafanaManagedReceivers {
|
||||||
|
receivers.Receivers = append(receivers.Receivers, PostableGrafanaReceiverToGrafanaReceiver(receiver))
|
||||||
|
}
|
||||||
|
|
||||||
|
return &alertingNotify.APIReceiver{
|
||||||
|
ConfigReceiver: r.Receiver,
|
||||||
|
GrafanaReceivers: receivers,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func PostableApiAlertingConfigToApiReceivers(c apimodels.PostableApiAlertingConfig) []*alertingNotify.APIReceiver {
|
||||||
|
apiReceivers := make([]*alertingNotify.APIReceiver, 0, len(c.Receivers))
|
||||||
|
for _, receiver := range c.Receivers {
|
||||||
|
apiReceivers = append(apiReceivers, PostableApiReceiverToApiReceiver(receiver))
|
||||||
|
}
|
||||||
|
return apiReceivers
|
||||||
|
}
|
143
pkg/services/ngalert/notifier/compat_test.go
Normal file
143
pkg/services/ngalert/notifier/compat_test.go
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
package notifier
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
alertingNotify "github.com/grafana/alerting/notify"
|
||||||
|
"github.com/prometheus/alertmanager/config"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
apimodels "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestPostableGrafanaReceiverToGrafanaReceiver(t *testing.T) {
|
||||||
|
r := &apimodels.PostableGrafanaReceiver{
|
||||||
|
UID: "test-uid",
|
||||||
|
Name: "test-name",
|
||||||
|
Type: "slack",
|
||||||
|
DisableResolveMessage: false,
|
||||||
|
Settings: apimodels.RawMessage(`{ "data" : "test" }`),
|
||||||
|
SecureSettings: map[string]string{
|
||||||
|
"test": "data",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
actual := PostableGrafanaReceiverToGrafanaReceiver(r)
|
||||||
|
require.Equal(t, alertingNotify.GrafanaReceiver{
|
||||||
|
UID: "test-uid",
|
||||||
|
Name: "test-name",
|
||||||
|
Type: "slack",
|
||||||
|
DisableResolveMessage: false,
|
||||||
|
Settings: json.RawMessage(`{ "data" : "test" }`),
|
||||||
|
SecureSettings: map[string]string{
|
||||||
|
"test": "data",
|
||||||
|
},
|
||||||
|
}, *actual)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPostableApiReceiverToApiReceiver(t *testing.T) {
|
||||||
|
t.Run("returns empty when no receivers", func(t *testing.T) {
|
||||||
|
r := &apimodels.PostableApiReceiver{
|
||||||
|
Receiver: config.Receiver{
|
||||||
|
Name: "test-receiver",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
actual := PostableApiReceiverToApiReceiver(r)
|
||||||
|
require.Empty(t, actual.Receivers)
|
||||||
|
require.Equal(t, r.Receiver, actual.ConfigReceiver)
|
||||||
|
})
|
||||||
|
t.Run("converts receivers", func(t *testing.T) {
|
||||||
|
r := &apimodels.PostableApiReceiver{
|
||||||
|
Receiver: config.Receiver{
|
||||||
|
Name: "test-receiver",
|
||||||
|
},
|
||||||
|
PostableGrafanaReceivers: apimodels.PostableGrafanaReceivers{
|
||||||
|
GrafanaManagedReceivers: []*apimodels.PostableGrafanaReceiver{
|
||||||
|
{
|
||||||
|
UID: "test-uid",
|
||||||
|
Name: "test-name",
|
||||||
|
Type: "slack",
|
||||||
|
DisableResolveMessage: false,
|
||||||
|
Settings: apimodels.RawMessage(`{ "data" : "test" }`),
|
||||||
|
SecureSettings: map[string]string{
|
||||||
|
"test": "data",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
UID: "test-uid2",
|
||||||
|
Name: "test-name2",
|
||||||
|
Type: "webhook",
|
||||||
|
DisableResolveMessage: false,
|
||||||
|
Settings: apimodels.RawMessage(`{ "data2" : "test2" }`),
|
||||||
|
SecureSettings: map[string]string{
|
||||||
|
"test2": "data2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
actual := PostableApiReceiverToApiReceiver(r)
|
||||||
|
require.Len(t, actual.Receivers, 2)
|
||||||
|
require.Equal(t, r.Receiver, actual.ConfigReceiver)
|
||||||
|
require.Equal(t, *PostableGrafanaReceiverToGrafanaReceiver(r.GrafanaManagedReceivers[0]), *actual.Receivers[0])
|
||||||
|
require.Equal(t, *PostableGrafanaReceiverToGrafanaReceiver(r.GrafanaManagedReceivers[1]), *actual.Receivers[1])
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPostableApiAlertingConfigToApiReceivers(t *testing.T) {
|
||||||
|
t.Run("returns empty when no receivers", func(t *testing.T) {
|
||||||
|
r := apimodels.PostableApiAlertingConfig{
|
||||||
|
Config: apimodels.Config{},
|
||||||
|
}
|
||||||
|
actual := PostableApiAlertingConfigToApiReceivers(r)
|
||||||
|
require.Empty(t, actual)
|
||||||
|
})
|
||||||
|
c := apimodels.PostableApiAlertingConfig{
|
||||||
|
Config: apimodels.Config{},
|
||||||
|
Receivers: []*apimodels.PostableApiReceiver{
|
||||||
|
{
|
||||||
|
Receiver: config.Receiver{
|
||||||
|
Name: "test-receiver",
|
||||||
|
},
|
||||||
|
PostableGrafanaReceivers: apimodels.PostableGrafanaReceivers{
|
||||||
|
GrafanaManagedReceivers: []*apimodels.PostableGrafanaReceiver{
|
||||||
|
{
|
||||||
|
UID: "test-uid",
|
||||||
|
Name: "test-name",
|
||||||
|
Type: "slack",
|
||||||
|
DisableResolveMessage: false,
|
||||||
|
Settings: apimodels.RawMessage(`{ "data" : "test" }`),
|
||||||
|
SecureSettings: map[string]string{
|
||||||
|
"test": "data",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Receiver: config.Receiver{
|
||||||
|
Name: "test-receiver2",
|
||||||
|
},
|
||||||
|
PostableGrafanaReceivers: apimodels.PostableGrafanaReceivers{
|
||||||
|
GrafanaManagedReceivers: []*apimodels.PostableGrafanaReceiver{
|
||||||
|
{
|
||||||
|
UID: "test-uid2",
|
||||||
|
Name: "test-name1",
|
||||||
|
Type: "slack",
|
||||||
|
DisableResolveMessage: false,
|
||||||
|
Settings: apimodels.RawMessage(`{ "data" : "test" }`),
|
||||||
|
SecureSettings: map[string]string{
|
||||||
|
"test": "data",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
actual := PostableApiAlertingConfigToApiReceivers(c)
|
||||||
|
|
||||||
|
require.Len(t, actual, 2)
|
||||||
|
require.Equal(t, PostableApiReceiverToApiReceiver(c.Receivers[0]), actual[0])
|
||||||
|
require.Equal(t, PostableApiReceiverToApiReceiver(c.Receivers[1]), actual[1])
|
||||||
|
}
|
@ -97,31 +97,12 @@ type AlertingConfiguration struct {
|
|||||||
AlertmanagerTemplates *alertingNotify.Template
|
AlertmanagerTemplates *alertingNotify.Template
|
||||||
|
|
||||||
IntegrationsFunc func(receivers []*api.PostableApiReceiver, templates *alertingNotify.Template) (map[string][]*alertingNotify.Integration, error)
|
IntegrationsFunc func(receivers []*api.PostableApiReceiver, templates *alertingNotify.Template) (map[string][]*alertingNotify.Integration, error)
|
||||||
ReceiverIntegrationsFunc func(r *api.PostableGrafanaReceiver, tmpl *alertingNotify.Template) (alertingNotify.NotificationChannel, error)
|
ReceiverIntegrationsFunc func(r *alertingNotify.GrafanaReceiver, tmpl *alertingNotify.Template) (alertingNotify.NotificationChannel, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a AlertingConfiguration) BuildReceiverIntegrationsFunc() func(next *alertingNotify.GrafanaReceiver, tmpl *alertingNotify.Template) (alertingNotify.Notifier, error) {
|
func (a AlertingConfiguration) BuildReceiverIntegrationsFunc() func(next *alertingNotify.GrafanaReceiver, tmpl *alertingNotify.Template) (alertingNotify.Notifier, error) {
|
||||||
return func(next *alertingNotify.GrafanaReceiver, tmpl *alertingNotify.Template) (alertingNotify.Notifier, error) {
|
return func(next *alertingNotify.GrafanaReceiver, tmpl *alertingNotify.Template) (alertingNotify.Notifier, error) {
|
||||||
// TODO: We shouldn't need to do all of this marshalling - there should be no difference between types.
|
return a.ReceiverIntegrationsFunc(next, tmpl)
|
||||||
var out api.RawMessage
|
|
||||||
settingsJSON, err := json.Marshal(next.Settings)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("unable to marshal settings to JSON: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = out.UnmarshalJSON(settingsJSON)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("unable to marshal JSON to RawMessage: %v", err)
|
|
||||||
}
|
|
||||||
gr := &api.PostableGrafanaReceiver{
|
|
||||||
UID: next.UID,
|
|
||||||
Name: next.Name,
|
|
||||||
Type: next.Type,
|
|
||||||
DisableResolveMessage: next.DisableResolveMessage,
|
|
||||||
Settings: out,
|
|
||||||
SecureSettings: next.SecureSettings,
|
|
||||||
}
|
|
||||||
return a.ReceiverIntegrationsFunc(gr, tmpl)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,8 +3,6 @@ package notifier
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
alertingNotify "github.com/grafana/alerting/notify"
|
alertingNotify "github.com/grafana/alerting/notify"
|
||||||
@ -16,10 +14,6 @@ import (
|
|||||||
apimodels "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
|
apimodels "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
ErrNoReceivers = errors.New("no receivers")
|
|
||||||
)
|
|
||||||
|
|
||||||
type TestReceiversResult struct {
|
type TestReceiversResult struct {
|
||||||
Alert types.Alert
|
Alert types.Alert
|
||||||
Receivers []TestReceiverResult
|
Receivers []TestReceiverResult
|
||||||
@ -38,24 +32,6 @@ type TestReceiverConfigResult struct {
|
|||||||
Error error
|
Error error
|
||||||
}
|
}
|
||||||
|
|
||||||
type InvalidReceiverError struct {
|
|
||||||
Receiver *apimodels.PostableGrafanaReceiver
|
|
||||||
Err error
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e InvalidReceiverError) Error() string {
|
|
||||||
return fmt.Sprintf("the receiver is invalid: %s", e.Err)
|
|
||||||
}
|
|
||||||
|
|
||||||
type ReceiverTimeoutError struct {
|
|
||||||
Receiver *apimodels.PostableGrafanaReceiver
|
|
||||||
Err error
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e ReceiverTimeoutError) Error() string {
|
|
||||||
return fmt.Sprintf("the receiver timed out: %s", e.Err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (am *Alertmanager) TestReceivers(ctx context.Context, c apimodels.TestReceiversConfigBodyParams) (*TestReceiversResult, error) {
|
func (am *Alertmanager) TestReceivers(ctx context.Context, c apimodels.TestReceiversConfigBodyParams) (*TestReceiversResult, error) {
|
||||||
receivers := make([]*alertingNotify.APIReceiver, 0, len(c.Receivers))
|
receivers := make([]*alertingNotify.APIReceiver, 0, len(c.Receivers))
|
||||||
for _, r := range c.Receivers {
|
for _, r := range c.Receivers {
|
||||||
|
@ -121,7 +121,7 @@ func (m *migration) setupAlertmanagerConfigs(rulesPerOrg map[int64]map[*alertRul
|
|||||||
|
|
||||||
// Validate the alertmanager configuration produced, this gives a chance to catch bad configuration at migration time.
|
// Validate the alertmanager configuration produced, this gives a chance to catch bad configuration at migration time.
|
||||||
// Validation between legacy and unified alerting can be different (e.g. due to bug fixes) so this would fail the migration in that case.
|
// Validation between legacy and unified alerting can be different (e.g. due to bug fixes) so this would fail the migration in that case.
|
||||||
if err := m.validateAlertmanagerConfig(orgID, amConfig); err != nil {
|
if err := m.validateAlertmanagerConfig(amConfig); err != nil {
|
||||||
return nil, fmt.Errorf("failed to validate AlertmanagerConfig in orgId %d: %w", orgID, err)
|
return nil, fmt.Errorf("failed to validate AlertmanagerConfig in orgId %d: %w", orgID, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ package ualert
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/base64"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -12,9 +11,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
alertingLogging "github.com/grafana/alerting/logging"
|
|
||||||
alertingNotify "github.com/grafana/alerting/notify"
|
alertingNotify "github.com/grafana/alerting/notify"
|
||||||
"github.com/grafana/alerting/receivers"
|
|
||||||
pb "github.com/prometheus/alertmanager/silence/silencepb"
|
pb "github.com/prometheus/alertmanager/silence/silencepb"
|
||||||
"xorm.io/xorm"
|
"xorm.io/xorm"
|
||||||
|
|
||||||
@ -475,32 +472,21 @@ func (m *migration) writeAlertmanagerConfig(orgID int64, amConfig *PostableUserC
|
|||||||
}
|
}
|
||||||
|
|
||||||
// validateAlertmanagerConfig validates the alertmanager configuration produced by the migration against the receivers.
|
// validateAlertmanagerConfig validates the alertmanager configuration produced by the migration against the receivers.
|
||||||
func (m *migration) validateAlertmanagerConfig(orgID int64, config *PostableUserConfig) error {
|
func (m *migration) validateAlertmanagerConfig(config *PostableUserConfig) error {
|
||||||
for _, r := range config.AlertmanagerConfig.Receivers {
|
for _, r := range config.AlertmanagerConfig.Receivers {
|
||||||
for _, gr := range r.GrafanaManagedReceivers {
|
for _, gr := range r.GrafanaManagedReceivers {
|
||||||
// First, let's decode the secure settings - given they're stored as base64.
|
|
||||||
secureSettings := make(map[string][]byte, len(gr.SecureSettings))
|
|
||||||
for k, v := range gr.SecureSettings {
|
|
||||||
d, err := base64.StdEncoding.DecodeString(v)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
secureSettings[k] = d
|
|
||||||
}
|
|
||||||
|
|
||||||
data, err := gr.Settings.MarshalJSON()
|
data, err := gr.Settings.MarshalJSON()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
var (
|
var (
|
||||||
cfg = &receivers.NotificationChannelConfig{
|
cfg = &alertingNotify.GrafanaReceiver{
|
||||||
UID: gr.UID,
|
UID: gr.UID,
|
||||||
OrgID: orgID,
|
|
||||||
Name: gr.Name,
|
Name: gr.Name,
|
||||||
Type: gr.Type,
|
Type: gr.Type,
|
||||||
DisableResolveMessage: gr.DisableResolveMessage,
|
DisableResolveMessage: gr.DisableResolveMessage,
|
||||||
Settings: data,
|
Settings: data,
|
||||||
SecureSettings: secureSettings,
|
SecureSettings: gr.SecureSettings,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -517,17 +503,9 @@ func (m *migration) validateAlertmanagerConfig(orgID int64, config *PostableUser
|
|||||||
}
|
}
|
||||||
return fallback
|
return fallback
|
||||||
}
|
}
|
||||||
receiverFactory, exists := alertingNotify.Factory(gr.Type)
|
_, err = alertingNotify.BuildReceiverConfiguration(context.Background(), &alertingNotify.APIReceiver{
|
||||||
if !exists {
|
GrafanaReceivers: alertingNotify.GrafanaReceivers{Receivers: []*alertingNotify.GrafanaReceiver{cfg}},
|
||||||
return fmt.Errorf("notifier %s is not supported", gr.Type)
|
}, decryptFunc)
|
||||||
}
|
|
||||||
factoryConfig, err := receivers.NewFactoryConfig(cfg, nil, decryptFunc, nil, nil, func(ctx ...interface{}) alertingLogging.Logger {
|
|
||||||
return &alertingLogging.FakeLogger{}
|
|
||||||
}, setting.BuildVersion)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
_, err = receiverFactory(factoryConfig)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -65,14 +65,14 @@ func Test_validateAlertmanagerConfig(t *testing.T) {
|
|||||||
name: "when a slack receiver does not have a valid URL - it should error",
|
name: "when a slack receiver does not have a valid URL - it should error",
|
||||||
receivers: []*PostableGrafanaReceiver{
|
receivers: []*PostableGrafanaReceiver{
|
||||||
{
|
{
|
||||||
UID: util.GenerateShortUID(),
|
UID: "test-uid",
|
||||||
Name: "SlackWithBadURL",
|
Name: "SlackWithBadURL",
|
||||||
Type: "slack",
|
Type: "slack",
|
||||||
Settings: simplejson.NewFromAny(map[string]interface{}{}),
|
Settings: simplejson.NewFromAny(map[string]interface{}{}),
|
||||||
SecureSettings: map[string]string{"url": invalidUri},
|
SecureSettings: map[string]string{"url": invalidUri},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
err: fmt.Errorf("failed to validate receiver \"SlackWithBadURL\" of type \"slack\": invalid URL %q", invalidUri),
|
err: fmt.Errorf("failed to validate receiver \"SlackWithBadURL\" of type \"slack\": failed to parse notifier SlackWithBadURL (UID: test-uid): invalid URL %q", invalidUri),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "when a slack receiver has an invalid recipient - it should not error",
|
name: "when a slack receiver has an invalid recipient - it should not error",
|
||||||
@ -103,11 +103,10 @@ func Test_validateAlertmanagerConfig(t *testing.T) {
|
|||||||
for _, tt := range tc {
|
for _, tt := range tc {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
mg := newTestMigration(t)
|
mg := newTestMigration(t)
|
||||||
orgID := int64(1)
|
|
||||||
|
|
||||||
config := configFromReceivers(t, tt.receivers)
|
config := configFromReceivers(t, tt.receivers)
|
||||||
require.NoError(t, config.EncryptSecureSettings()) // make sure we encrypt the settings
|
require.NoError(t, config.EncryptSecureSettings()) // make sure we encrypt the settings
|
||||||
err := mg.validateAlertmanagerConfig(orgID, config)
|
err := mg.validateAlertmanagerConfig(config)
|
||||||
if tt.err != nil {
|
if tt.err != nil {
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
require.EqualError(t, err, tt.err.Error())
|
require.EqualError(t, err, tt.err.Error())
|
||||||
|
Loading…
Reference in New Issue
Block a user