Alerting: replace usage of simplejson to json.RawMessage in NotificationChannelConfig (#60423)

* introduce alias for json.RawMessage with name RawMessage. This is needed to keep raw JSON and implement a marshaler for YAML, which does not seem to be used but there are tests that fail.
* replace usage of simplejson with RawMessage in NotificationChannelConfig
* remove usage of simplejson in tests
* change migration code to convert simplejson to raw message
This commit is contained in:
Yuri Tseretyan 2022-12-16 13:01:06 -05:00 committed by GitHub
parent 09bb4423d2
commit 9ad45aedcf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 257 additions and 161 deletions

View File

@ -1,15 +1,17 @@
package api
import (
"encoding/json"
"fmt"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
amConfig "github.com/prometheus/alertmanager/config"
"github.com/prometheus/alertmanager/pkg/labels"
apimodels "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
ngmodels "github.com/grafana/grafana/pkg/services/ngalert/models"
"github.com/grafana/grafana/pkg/util/cmputil"
amConfig "github.com/prometheus/alertmanager/config"
"github.com/prometheus/alertmanager/pkg/labels"
)
func (srv AlertmanagerSrv) provenanceGuard(currentConfig apimodels.GettableUserConfig, newConfig apimodels.PostableUserConfig) error {
@ -96,11 +98,16 @@ func checkContactPoints(currReceivers []*apimodels.GettableApiReceiver, newRecei
return editErr
}
}
existingSettings, err := contactPoint.Settings.Map()
existingSettings := map[string]interface{}{}
err := json.Unmarshal(contactPoint.Settings, &existingSettings)
if err != nil {
return err
}
newSettings := map[string]interface{}{}
err = json.Unmarshal(contactPoint.Settings, &newSettings)
if err != nil {
return err
}
newSettings, err := postedContactPoint.Settings.Map()
if err != nil {
return err
}

View File

@ -3,14 +3,14 @@ package api
import (
"testing"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
"github.com/grafana/grafana/pkg/services/ngalert/models"
amConfig "github.com/prometheus/alertmanager/config"
"github.com/prometheus/alertmanager/pkg/labels"
"github.com/prometheus/alertmanager/timeinterval"
"github.com/prometheus/common/model"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
"github.com/grafana/grafana/pkg/services/ngalert/models"
)
func TestCheckRoute(t *testing.T) {
@ -319,9 +319,9 @@ func defaultGettableReceiver(t *testing.T, uid string, provenance models.Provena
SecureFields: map[string]bool{
"url": true,
},
Settings: simplejson.NewFromAny(map[string]interface{}{
"hello": "world",
}),
Settings: definitions.RawMessage(`{
"hello": "world"
}`),
},
},
},
@ -338,9 +338,9 @@ func defaultPostableReceiver(t *testing.T, uid string) *definitions.PostableApiR
Name: "yeah",
Type: "slack",
DisableResolveMessage: true,
Settings: simplejson.NewFromAny(map[string]interface{}{
"hello": "world",
}),
Settings: definitions.RawMessage(`{
"hello": "world"
}`),
},
},
},

View File

@ -17,7 +17,6 @@ import (
"github.com/prometheus/common/model"
"gopkg.in/yaml.v3"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/services/ngalert/models"
"github.com/grafana/grafana/pkg/services/secrets"
"github.com/grafana/grafana/pkg/util"
@ -964,12 +963,54 @@ func AllReceivers(route *config.Route) (res []string) {
return res
}
type RawMessage json.RawMessage // This type alias adds YAML marshaling to the json.RawMessage.
// MarshalJSON returns m as the JSON encoding of m.
func (r RawMessage) MarshalJSON() ([]byte, error) {
return json.Marshal(json.RawMessage(r))
}
func (r *RawMessage) UnmarshalJSON(data []byte) error {
var raw json.RawMessage
err := json.Unmarshal(data, &raw)
if err != nil {
return err
}
*r = RawMessage(raw)
return nil
}
func (r *RawMessage) UnmarshalYAML(unmarshal func(interface{}) error) error {
var data interface{}
if err := unmarshal(&data); err != nil {
return err
}
bytes, err := json.Marshal(data)
if err != nil {
return err
}
*r = bytes
return nil
}
func (r RawMessage) MarshalYAML() (interface{}, error) {
if r == nil {
return nil, nil
}
var d interface{}
err := json.Unmarshal(r, &d)
if err != nil {
return nil, err
}
return d, nil
}
type GettableGrafanaReceiver struct {
UID string `json:"uid"`
Name string `json:"name"`
Type string `json:"type"`
DisableResolveMessage bool `json:"disableResolveMessage"`
Settings *simplejson.Json `json:"settings"`
Settings RawMessage `json:"settings,omitempty"`
SecureFields map[string]bool `json:"secureFields"`
Provenance models.Provenance `json:"provenance,omitempty"`
}
@ -979,7 +1020,7 @@ type PostableGrafanaReceiver struct {
Name string `json:"name"`
Type string `json:"type"`
DisableResolveMessage bool `json:"disableResolveMessage"`
Settings *simplejson.Json `json:"settings"`
Settings RawMessage `json:"settings,omitempty"`
SecureSettings map[string]string `json:"secureSettings"`
}

View File

@ -1040,3 +1040,49 @@ func Test_Marshaling_Validation(t *testing.T) {
expected := []model.LabelName{"alertname"}
require.Equal(t, expected, tmp.AlertmanagerConfig.Config.Route.GroupBy)
}
func Test_RawMessageMarshaling(t *testing.T) {
type Data struct {
Field RawMessage `json:"field" yaml:"field"`
}
t.Run("should unmarshal nil", func(t *testing.T) {
v := Data{
Field: nil,
}
data, err := json.Marshal(v)
require.NoError(t, err)
assert.JSONEq(t, `{ "field": null }`, string(data))
var n Data
require.NoError(t, json.Unmarshal(data, &n))
assert.Equal(t, RawMessage("null"), n.Field)
data, err = yaml.Marshal(&v)
require.NoError(t, err)
assert.Equal(t, "field: null\n", string(data))
require.NoError(t, yaml.Unmarshal(data, &n))
assert.Nil(t, n.Field)
})
t.Run("should unmarshal value", func(t *testing.T) {
v := Data{
Field: RawMessage(`{ "data": "test"}`),
}
data, err := json.Marshal(v)
require.NoError(t, err)
assert.JSONEq(t, `{"field":{"data":"test"}}`, string(data))
var n Data
require.NoError(t, json.Unmarshal(data, &n))
assert.Equal(t, RawMessage(`{"data":"test"}`), n.Field)
data, err = yaml.Marshal(&v)
require.NoError(t, err)
assert.Equal(t, "field:\n data: test\n", string(data))
require.NoError(t, yaml.Unmarshal(data, &n))
assert.Equal(t, RawMessage(`{"data":"test"}`), n.Field)
})
}

View File

@ -108,8 +108,12 @@ func (e *EmbeddedContactPoint) Valid(decryptFunc channels.GetDecryptedValueFn) e
if !exists {
return fmt.Errorf("unknown type '%s'", e.Type)
}
jsonBytes, err := e.Settings.MarshalJSON()
if err != nil {
return err
}
cfg, _ := channels.NewFactoryConfig(&channels.NotificationChannelConfig{
Settings: e.Settings,
Settings: jsonBytes,
Type: e.Type,
}, nil, decryptFunc, nil, nil, func(ctx ...interface{}) channels.Logger {
return &channels.FakeLogger{}

View File

@ -510,7 +510,7 @@ func (am *Alertmanager) buildReceiverIntegration(r *apimodels.PostableGrafanaRec
Name: r.Name,
Type: r.Type,
DisableResolveMessage: r.DisableResolveMessage,
Settings: r.Settings,
Settings: json.RawMessage(r.Settings),
SecureSettings: secureSettings,
}
)

View File

@ -11,6 +11,8 @@ import (
"github.com/prometheus/alertmanager/template"
"github.com/prometheus/alertmanager/types"
"github.com/prometheus/common/model"
"github.com/grafana/grafana/pkg/components/simplejson"
)
// GetDecryptedValueFn is a function that returns the decrypted value of
@ -25,7 +27,11 @@ type AlertmanagerConfig struct {
}
func NewAlertmanagerConfig(config *NotificationChannelConfig, fn GetDecryptedValueFn) (*AlertmanagerConfig, error) {
urlStr := config.Settings.Get("url").MustString()
simpleConfig, err := simplejson.NewJson(config.Settings)
if err != nil {
return nil, err
}
urlStr := simpleConfig.Get("url").MustString()
if urlStr == "" {
return nil, errors.New("could not find url property in settings")
}
@ -48,8 +54,8 @@ func NewAlertmanagerConfig(config *NotificationChannelConfig, fn GetDecryptedVal
return &AlertmanagerConfig{
NotificationChannelConfig: config,
URLs: urls,
BasicAuthUser: config.Settings.Get("basicAuthUser").MustString(),
BasicAuthPassword: fn(context.Background(), config.SecureSettings, "basicAuthPassword", config.Settings.Get("basicAuthPassword").MustString()),
BasicAuthUser: simpleConfig.Get("basicAuthUser").MustString(),
BasicAuthPassword: fn(context.Background(), config.SecureSettings, "basicAuthPassword", simpleConfig.Get("basicAuthPassword").MustString()),
}, nil
}

View File

@ -7,7 +7,6 @@ import (
"net/url"
"testing"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/services/secrets/fakes"
secretsManager "github.com/grafana/grafana/pkg/services/secrets/manager"
@ -46,14 +45,12 @@ func TestNewAlertmanagerNotifier(t *testing.T) {
}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
settingsJSON, err := simplejson.NewJson([]byte(c.settings))
require.NoError(t, err)
secureSettings := make(map[string][]byte)
m := &NotificationChannelConfig{
Name: c.receiverName,
Type: "prometheus-alertmanager",
Settings: settingsJSON,
Settings: json.RawMessage(c.settings),
SecureSettings: secureSettings,
}
@ -143,7 +140,7 @@ func TestAlertmanagerNotifier_Notify(t *testing.T) {
}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
settingsJSON, err := simplejson.NewJson([]byte(c.settings))
settingsJSON := json.RawMessage(c.settings)
require.NoError(t, err)
secureSettings := make(map[string][]byte)

View File

@ -9,6 +9,8 @@ import (
"github.com/prometheus/alertmanager/template"
"github.com/prometheus/alertmanager/types"
"github.com/grafana/grafana/pkg/components/simplejson"
)
const defaultDingdingMsgType = "link"
@ -21,15 +23,19 @@ type dingDingSettings struct {
}
func buildDingDingSettings(fc FactoryConfig) (*dingDingSettings, error) {
URL := fc.Config.Settings.Get("url").MustString()
settings, err := simplejson.NewJson(fc.Config.Settings)
if err != nil {
return nil, err
}
URL := settings.Get("url").MustString()
if URL == "" {
return nil, errors.New("could not find url property in settings")
}
return &dingDingSettings{
URL: URL,
MessageType: fc.Config.Settings.Get("msgType").MustString(defaultDingdingMsgType),
Title: fc.Config.Settings.Get("title").MustString(DefaultMessageTitleEmbed),
Message: fc.Config.Settings.Get("message").MustString(DefaultMessageEmbed),
MessageType: settings.Get("msgType").MustString(defaultDingdingMsgType),
Title: settings.Get("title").MustString(DefaultMessageTitleEmbed),
Message: settings.Get("message").MustString(DefaultMessageEmbed),
}, nil
}

View File

@ -10,8 +10,6 @@ import (
"github.com/prometheus/alertmanager/types"
"github.com/prometheus/common/model"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/components/simplejson"
)
func TestDingdingNotifier(t *testing.T) {
@ -166,15 +164,12 @@ func TestDingdingNotifier(t *testing.T) {
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
settingsJSON, err := simplejson.NewJson([]byte(c.settings))
require.NoError(t, err)
webhookSender := mockNotificationService()
fc := FactoryConfig{
Config: &NotificationChannelConfig{
Name: "dingding_testing",
Type: "dingding",
Settings: settingsJSON,
Settings: json.RawMessage(c.settings),
},
// TODO: allow changing the associated values for different tests.
NotificationService: webhookSender,

View File

@ -59,7 +59,11 @@ func DiscordFactory(fc FactoryConfig) (NotificationChannel, error) {
}
func newDiscordNotifier(fc FactoryConfig) (*DiscordNotifier, error) {
dUrl := fc.Config.Settings.Get("url").MustString()
settings, err := simplejson.NewJson(fc.Config.Settings)
if err != nil {
return nil, err
}
dUrl := settings.Get("url").MustString()
if dUrl == "" {
return nil, errors.New("could not find webhook url property in settings")
}
@ -71,11 +75,11 @@ func newDiscordNotifier(fc FactoryConfig) (*DiscordNotifier, error) {
images: fc.ImageStore,
tmpl: fc.Template,
settings: discordSettings{
Title: fc.Config.Settings.Get("title").MustString(DefaultMessageTitleEmbed),
Content: fc.Config.Settings.Get("message").MustString(DefaultMessageEmbed),
AvatarURL: fc.Config.Settings.Get("avatar_url").MustString(),
Title: settings.Get("title").MustString(DefaultMessageTitleEmbed),
Content: settings.Get("message").MustString(DefaultMessageEmbed),
AvatarURL: settings.Get("avatar_url").MustString(),
WebhookURL: dUrl,
UseDiscordUsername: fc.Config.Settings.Get("use_discord_username").MustBool(false),
UseDiscordUsername: settings.Get("use_discord_username").MustBool(false),
},
}, nil
}

View File

@ -11,7 +11,6 @@ import (
"github.com/prometheus/common/model"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/setting"
)
@ -287,8 +286,6 @@ func TestDiscordNotifier(t *testing.T) {
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
settingsJson, err := simplejson.NewJson([]byte(c.settings))
require.NoError(t, err)
webhookSender := mockNotificationService()
imageStore := &UnavailableImageStore{}
@ -296,7 +293,7 @@ func TestDiscordNotifier(t *testing.T) {
Config: &NotificationChannelConfig{
Name: "discord_testing",
Type: "discord",
Settings: settingsJson,
Settings: json.RawMessage(c.settings),
},
ImageStore: imageStore,
// TODO: allow changing the associated values for different tests.

View File

@ -11,6 +11,7 @@ import (
"github.com/prometheus/alertmanager/template"
"github.com/prometheus/alertmanager/types"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/util"
)
@ -48,7 +49,11 @@ func EmailFactory(fc FactoryConfig) (NotificationChannel, error) {
}
func NewEmailConfig(config *NotificationChannelConfig) (*EmailConfig, error) {
addressesString := config.Settings.Get("addresses").MustString()
settings, err := simplejson.NewJson(config.Settings)
if err != nil {
return nil, err
}
addressesString := settings.Get("addresses").MustString()
if addressesString == "" {
return nil, errors.New("could not find addresses in settings")
}
@ -56,9 +61,9 @@ func NewEmailConfig(config *NotificationChannelConfig) (*EmailConfig, error) {
addresses := util.SplitEmails(addressesString)
return &EmailConfig{
NotificationChannelConfig: config,
SingleEmail: config.Settings.Get("singleEmail").MustBool(false),
Message: config.Settings.Get("message").MustString(),
Subject: config.Settings.Get("subject").MustString(DefaultMessageTitleEmbed),
SingleEmail: settings.Get("singleEmail").MustBool(false),
Message: settings.Get("message").MustString(),
Subject: settings.Get("subject").MustString(DefaultMessageTitleEmbed),
Addresses: addresses,
}, nil
}

View File

@ -2,6 +2,7 @@ package channels
import (
"context"
"encoding/json"
"net/url"
"testing"
@ -10,7 +11,6 @@ import (
"github.com/prometheus/common/model"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/services/notifications"
)
@ -22,9 +22,8 @@ func TestEmailNotifier(t *testing.T) {
tmpl.ExternalURL = externalURL
t.Run("empty settings should return error", func(t *testing.T) {
json := `{ }`
settingsJSON, _ := simplejson.NewJson([]byte(json))
jsonData := `{ }`
settingsJSON := json.RawMessage(jsonData)
model := &NotificationChannelConfig{
Name: "ops",
Type: "email",
@ -36,18 +35,16 @@ func TestEmailNotifier(t *testing.T) {
})
t.Run("with the correct settings it should not fail and produce the expected command", func(t *testing.T) {
json := `{
jsonData := `{
"addresses": "someops@example.com;somedev@example.com",
"message": "{{ template \"default.title\" . }}"
}`
settingsJSON, err := simplejson.NewJson([]byte(json))
require.NoError(t, err)
emailSender := mockNotificationService()
cfg, err := NewEmailConfig(&NotificationChannelConfig{
Name: "ops",
Type: "email",
Settings: settingsJSON,
Settings: json.RawMessage(jsonData),
})
require.NoError(t, err)
emailNotifier := NewEmailNotifier(cfg, &FakeLogger{}, emailSender, &UnavailableImageStore{}, tmpl)
@ -270,24 +267,23 @@ func TestEmailNotifierIntegration(t *testing.T) {
func createSut(t *testing.T, messageTmpl string, subjectTmpl string, emailTmpl *template.Template, ns *emailSender) *EmailNotifier {
t.Helper()
json := `{
"addresses": "someops@example.com;somedev@example.com",
"singleEmail": true
}`
settingsJSON, err := simplejson.NewJson([]byte(json))
jsonData := map[string]interface{}{
"addresses": "someops@example.com;somedev@example.com",
"singleEmail": true,
}
if messageTmpl != "" {
settingsJSON.Set("message", messageTmpl)
jsonData["message"] = messageTmpl
}
if subjectTmpl != "" {
settingsJSON.Set("subject", subjectTmpl)
jsonData["subject"] = subjectTmpl
}
bytes, err := json.Marshal(jsonData)
require.NoError(t, err)
cfg, err := NewEmailConfig(&NotificationChannelConfig{
Name: "ops",
Type: "email",
Settings: settingsJSON,
Settings: bytes,
})
require.NoError(t, err)
emailNotifier := NewEmailNotifier(cfg, &FakeLogger{}, ns, &UnavailableImageStore{}, emailTmpl)

View File

@ -11,6 +11,7 @@ import (
"github.com/prometheus/alertmanager/template"
"github.com/prometheus/alertmanager/types"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/setting"
)
@ -49,7 +50,11 @@ func newGoogleChatNotifier(fc FactoryConfig) (*GoogleChatNotifier, error) {
return nil, fmt.Errorf("failed to unmarshal settings: %w", err)
}
URL := fc.Config.Settings.Get("url").MustString()
rawsettings, err := simplejson.NewJson(fc.Config.Settings)
if err != nil {
return nil, err
}
URL := rawsettings.Get("url").MustString()
if URL == "" {
return nil, errors.New("could not find url property in settings")
}
@ -62,8 +67,8 @@ func newGoogleChatNotifier(fc FactoryConfig) (*GoogleChatNotifier, error) {
tmpl: fc.Template,
settings: googleChatSettings{
URL: URL,
Title: fc.Config.Settings.Get("title").MustString(DefaultMessageTitleEmbed),
Content: fc.Config.Settings.Get("message").MustString(DefaultMessageEmbed),
Title: rawsettings.Get("title").MustString(DefaultMessageTitleEmbed),
Content: rawsettings.Get("message").MustString(DefaultMessageEmbed),
},
}, nil
}

View File

@ -12,7 +12,6 @@ import (
"github.com/prometheus/common/model"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/setting"
)
@ -462,9 +461,6 @@ func TestGoogleChatNotifier(t *testing.T) {
require.NoError(t, err)
tmpl.ExternalURL = externalURL
settingsJSON, err := simplejson.NewJson([]byte(c.settings))
require.NoError(t, err)
webhookSender := mockNotificationService()
imageStore := &UnavailableImageStore{}
@ -472,7 +468,7 @@ func TestGoogleChatNotifier(t *testing.T) {
Config: &NotificationChannelConfig{
Name: "googlechat_testing",
Type: "googlechat",
Settings: settingsJSON,
Settings: json.RawMessage(c.settings),
},
ImageStore: imageStore,
NotificationService: webhookSender,

View File

@ -45,16 +45,20 @@ func KafkaFactory(fc FactoryConfig) (NotificationChannel, error) {
// newKafkaNotifier is the constructor function for the Kafka notifier.
func newKafkaNotifier(fc FactoryConfig) (*KafkaNotifier, error) {
endpoint := fc.Config.Settings.Get("kafkaRestProxy").MustString()
settings, err := simplejson.NewJson(fc.Config.Settings)
if err != nil {
return nil, err
}
endpoint := settings.Get("kafkaRestProxy").MustString()
if endpoint == "" {
return nil, errors.New("could not find kafka rest proxy endpoint property in settings")
}
topic := fc.Config.Settings.Get("kafkaTopic").MustString()
topic := settings.Get("kafkaTopic").MustString()
if topic == "" {
return nil, errors.New("could not find kafka topic property in settings")
}
description := fc.Config.Settings.Get("description").MustString(DefaultMessageTitleEmbed)
details := fc.Config.Settings.Get("details").MustString(DefaultMessageEmbed)
description := settings.Get("description").MustString(DefaultMessageTitleEmbed)
details := settings.Get("details").MustString(DefaultMessageEmbed)
return &KafkaNotifier{
Base: NewBase(fc.Config),

View File

@ -2,6 +2,7 @@ package channels
import (
"context"
"encoding/json"
"net/url"
"testing"
@ -9,8 +10,6 @@ import (
"github.com/prometheus/alertmanager/types"
"github.com/prometheus/common/model"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/components/simplejson"
)
func TestKafkaNotifier(t *testing.T) {
@ -112,16 +111,13 @@ func TestKafkaNotifier(t *testing.T) {
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
settingsJSON, err := simplejson.NewJson([]byte(c.settings))
require.NoError(t, err)
webhookSender := mockNotificationService()
fc := FactoryConfig{
Config: &NotificationChannelConfig{
Name: "kafka_testing",
Type: "kafka",
Settings: settingsJSON,
Settings: json.RawMessage(c.settings),
},
ImageStore: images,
// TODO: allow changing the associated values for different tests.

View File

@ -9,6 +9,8 @@ import (
"github.com/prometheus/alertmanager/template"
"github.com/prometheus/alertmanager/types"
"github.com/grafana/grafana/pkg/components/simplejson"
)
var (
@ -44,12 +46,16 @@ func LineFactory(fc FactoryConfig) (NotificationChannel, error) {
// newLineNotifier is the constructor for the LINE notifier
func newLineNotifier(fc FactoryConfig) (*LineNotifier, error) {
token := fc.DecryptFunc(context.Background(), fc.Config.SecureSettings, "token", fc.Config.Settings.Get("token").MustString())
settings, err := simplejson.NewJson(fc.Config.Settings)
if err != nil {
return nil, err
}
token := fc.DecryptFunc(context.Background(), fc.Config.SecureSettings, "token", settings.Get("token").MustString())
if token == "" {
return nil, errors.New("could not find token in settings")
}
title := fc.Config.Settings.Get("title").MustString(DefaultMessageTitleEmbed)
description := fc.Config.Settings.Get("description").MustString(DefaultMessageEmbed)
title := settings.Get("title").MustString(DefaultMessageTitleEmbed)
description := settings.Get("description").MustString(DefaultMessageEmbed)
return &LineNotifier{
Base: NewBase(fc.Config),

View File

@ -2,6 +2,7 @@ package channels
import (
"context"
"encoding/json"
"net/url"
"testing"
@ -10,7 +11,6 @@ import (
"github.com/prometheus/common/model"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/services/secrets/fakes"
secretsManager "github.com/grafana/grafana/pkg/services/secrets/manager"
)
@ -96,8 +96,7 @@ func TestLineNotifier(t *testing.T) {
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
settingsJSON, err := simplejson.NewJson([]byte(c.settings))
require.NoError(t, err)
settingsJSON := json.RawMessage(c.settings)
secureSettings := make(map[string][]byte)
webhookSender := mockNotificationService()
secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore())

View File

@ -2,11 +2,11 @@ package channels
import (
"context"
"encoding/json"
"net/url"
"testing"
"time"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/services/secrets/fakes"
secretsManager "github.com/grafana/grafana/pkg/services/secrets/manager"
@ -230,8 +230,7 @@ func TestOpsgenieNotifier(t *testing.T) {
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
settingsJSON, err := simplejson.NewJson([]byte(c.settings))
require.NoError(t, err)
settingsJSON := json.RawMessage(c.settings)
secureSettings := make(map[string][]byte)
webhookSender := mockNotificationService()

View File

@ -15,7 +15,6 @@ import (
"github.com/prometheus/common/model"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/services/secrets/fakes"
secretsManager "github.com/grafana/grafana/pkg/services/secrets/manager"
)
@ -276,8 +275,7 @@ func TestPagerdutyNotifier(t *testing.T) {
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
settingsJSON, err := simplejson.NewJson([]byte(c.settings))
require.NoError(t, err)
settingsJSON := json.RawMessage(c.settings)
secureSettings := make(map[string][]byte)
webhookSender := mockNotificationService()
secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore())

View File

@ -3,6 +3,7 @@ package channels
import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"io"
@ -11,7 +12,6 @@ import (
"strings"
"testing"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/services/secrets/fakes"
secretsManager "github.com/grafana/grafana/pkg/services/secrets/manager"
@ -210,8 +210,7 @@ func TestPushoverNotifier(t *testing.T) {
})
t.Run(c.name, func(t *testing.T) {
settingsJSON, err := simplejson.NewJson([]byte(c.settings))
require.NoError(t, err)
settingsJSON := json.RawMessage(c.settings)
secureSettings := make(map[string][]byte)
webhookSender := mockNotificationService()

View File

@ -7,7 +7,6 @@ import (
"testing"
"time"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/services/secrets/fakes"
secretsManager "github.com/grafana/grafana/pkg/services/secrets/manager"
@ -137,8 +136,7 @@ func TestSensuGoNotifier(t *testing.T) {
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
settingsJSON, err := simplejson.NewJson([]byte(c.settings))
require.NoError(t, err)
settingsJSON := json.RawMessage(c.settings)
secureSettings := make(map[string][]byte)
m := &NotificationChannelConfig{

View File

@ -19,7 +19,6 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/services/secrets/fakes"
secretsManager "github.com/grafana/grafana/pkg/services/secrets/manager"
"github.com/grafana/grafana/pkg/setting"
@ -422,10 +421,6 @@ func setupSlackForTests(t *testing.T, settings string) (*SlackNotifier, *slackRe
URL: "https://www.example.com/test.png",
}},
}
settingsJSON, err := simplejson.NewJson([]byte(settings))
require.NoError(t, err)
secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore())
notificationService := mockNotificationService()
@ -433,7 +428,7 @@ func setupSlackForTests(t *testing.T, settings string) (*SlackNotifier, *slackRe
Config: &NotificationChannelConfig{
Name: "slack_testing",
Type: "slack",
Settings: settingsJSON,
Settings: json.RawMessage(settings),
SecureSettings: make(map[string][]byte),
},
ImageStore: images,

View File

@ -11,8 +11,6 @@ import (
"github.com/prometheus/alertmanager/types"
"github.com/prometheus/common/model"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/components/simplejson"
)
func TestTeamsNotifier(t *testing.T) {
@ -249,8 +247,7 @@ func TestTeamsNotifier(t *testing.T) {
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
settingsJSON, err := simplejson.NewJson([]byte(c.settings))
require.NoError(t, err)
settingsJSON := json.RawMessage(c.settings)
m := &NotificationChannelConfig{
Name: "teams_testing",

View File

@ -2,11 +2,11 @@ package channels
import (
"context"
"encoding/json"
"net/url"
"strings"
"testing"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/services/secrets/fakes"
secretsManager "github.com/grafana/grafana/pkg/services/secrets/manager"
@ -116,7 +116,7 @@ func TestTelegramNotifier(t *testing.T) {
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
settingsJSON, err := simplejson.NewJson([]byte(c.settings))
settingsJSON := json.RawMessage(c.settings)
require.NoError(t, err)
secureSettings := make(map[string][]byte)

View File

@ -2,10 +2,10 @@ package channels
import (
"context"
"encoding/json"
"net/url"
"testing"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/services/secrets/fakes"
secretsManager "github.com/grafana/grafana/pkg/services/secrets/manager"
@ -118,8 +118,7 @@ func TestThreemaNotifier(t *testing.T) {
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
settingsJSON, err := simplejson.NewJson([]byte(c.settings))
require.NoError(t, err)
settingsJSON := json.RawMessage(c.settings)
secureSettings := make(map[string][]byte)
webhookSender := mockNotificationService()
secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore())

View File

@ -24,8 +24,6 @@ import (
"github.com/grafana/grafana/pkg/services/ngalert/models"
"github.com/grafana/grafana/pkg/util"
"github.com/grafana/grafana/pkg/components/simplejson"
)
const (
@ -170,20 +168,12 @@ type NotificationChannelConfig struct {
Name string `json:"name"`
Type string `json:"type"`
DisableResolveMessage bool `json:"disableResolveMessage"`
Settings *simplejson.Json `json:"settings"`
Settings json.RawMessage `json:"settings"`
SecureSettings map[string][]byte `json:"secureSettings"`
}
func (c NotificationChannelConfig) unmarshalSettings(v interface{}) error {
ser, err := c.Settings.Encode()
if err != nil {
return err
}
err = json.Unmarshal(ser, v)
if err != nil {
return err
}
return nil
return json.Unmarshal(c.Settings, v)
}
type httpCfg struct {

View File

@ -11,7 +11,6 @@ import (
"github.com/prometheus/common/model"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/setting"
)
@ -188,8 +187,7 @@ func TestVictoropsNotifier(t *testing.T) {
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
settingsJSON, err := simplejson.NewJson([]byte(c.settings))
require.NoError(t, err)
settingsJSON := json.RawMessage(c.settings)
m := &NotificationChannelConfig{
Name: "victorops_testing",
@ -230,10 +228,11 @@ func TestVictoropsNotifier(t *testing.T) {
require.NotEmpty(t, webhookSender.Webhook.Url)
// Remove the non-constant timestamp
j, err := simplejson.NewJson([]byte(webhookSender.Webhook.Body))
data := make(map[string]interface{})
err = json.Unmarshal([]byte(webhookSender.Webhook.Body), &data)
require.NoError(t, err)
j.Del("timestamp")
b, err := j.MarshalJSON()
delete(data, "timestamp")
b, err := json.Marshal(data)
require.NoError(t, err)
body := string(b)

View File

@ -2,12 +2,12 @@ package channels
import (
"context"
"encoding/json"
"fmt"
"net/url"
"strings"
"testing"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/services/secrets/fakes"
secretsManager "github.com/grafana/grafana/pkg/services/secrets/manager"
@ -105,8 +105,7 @@ func TestWebexNotifier(t *testing.T) {
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
settingsJSON, err := simplejson.NewJson([]byte(c.settings))
require.NoError(t, err)
settingsJSON := json.RawMessage(c.settings)
secureSettings := make(map[string][]byte)
secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore())

View File

@ -7,7 +7,6 @@ import (
"net/url"
"testing"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/services/secrets/fakes"
secretsManager "github.com/grafana/grafana/pkg/services/secrets/manager"
@ -337,8 +336,7 @@ func TestWebhookNotifier(t *testing.T) {
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
settingsJSON, err := simplejson.NewJson([]byte(c.settings))
require.NoError(t, err)
settingsJSON := json.RawMessage(c.settings)
secureSettings := make(map[string][]byte)
m := &NotificationChannelConfig{

View File

@ -19,8 +19,6 @@ import (
"github.com/prometheus/common/model"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/components/simplejson"
)
func TestWeComNotifier(t *testing.T) {
@ -159,8 +157,7 @@ func TestWeComNotifier(t *testing.T) {
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
settingsJSON, err := simplejson.NewJson([]byte(c.settings))
require.NoError(t, err)
settingsJSON := json.RawMessage(c.settings)
m := &NotificationChannelConfig{
Name: "wecom_testing",
@ -345,13 +342,10 @@ func TestWeComNotifierAPIAPP(t *testing.T) {
}))
defer server.Close()
settingsJSON, err := simplejson.NewJson([]byte(tt.settings))
require.NoError(t, err)
m := &NotificationChannelConfig{
Name: "wecom_testing",
Type: "wecom",
Settings: settingsJSON,
Settings: json.RawMessage(tt.settings),
}
webhookSender := mockNotificationService()
@ -532,13 +526,10 @@ func TestWeComFactory(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
settingsJSON, err := simplejson.NewJson([]byte(tt.settings))
require.NoError(t, err)
m := &NotificationChannelConfig{
Name: "wecom_testing",
Type: "wecom",
Settings: settingsJSON,
Settings: json.RawMessage(tt.settings),
}
webhookSender := mockNotificationService()
@ -552,7 +543,7 @@ func TestWeComFactory(t *testing.T) {
Logger: &FakeLogger{},
}
_, err = WeComFactory(fc)
_, err := WeComFactory(fc)
if !tt.wantErr(t, err, fmt.Sprintf("WeComFactory(%v)", fc)) {
return
}

View File

@ -7,12 +7,14 @@ import (
"fmt"
"sort"
"github.com/prometheus/alertmanager/config"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/infra/log"
apimodels "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
"github.com/grafana/grafana/pkg/services/ngalert/models"
"github.com/grafana/grafana/pkg/services/secrets"
"github.com/grafana/grafana/pkg/util"
"github.com/prometheus/alertmanager/config"
)
type ContactPointService struct {
@ -55,12 +57,16 @@ func (ecp *ContactPointService) GetContactPoints(ctx context.Context, q ContactP
continue
}
simpleJson, err := simplejson.NewJson(contactPoint.Settings)
if err != nil {
return nil, err
}
embeddedContactPoint := apimodels.EmbeddedContactPoint{
UID: contactPoint.UID,
Type: contactPoint.Type,
Name: contactPoint.Name,
DisableResolveMessage: contactPoint.DisableResolveMessage,
Settings: contactPoint.Settings,
Settings: simpleJson,
}
if val, exists := provenances[embeddedContactPoint.UID]; exists && val != "" {
embeddedContactPoint.Provenance = string(val)
@ -96,12 +102,16 @@ func (ecp *ContactPointService) getContactPointDecrypted(ctx context.Context, or
if receiver.UID != uid {
continue
}
simpleJson, err := simplejson.NewJson(receiver.Settings)
if err != nil {
return apimodels.EmbeddedContactPoint{}, err
}
embeddedContactPoint := apimodels.EmbeddedContactPoint{
UID: receiver.UID,
Type: receiver.Type,
Name: receiver.Name,
DisableResolveMessage: receiver.DisableResolveMessage,
Settings: receiver.Settings,
Settings: simpleJson,
}
for k, v := range receiver.SecureSettings {
decryptedValue, err := ecp.decryptValue(v)
@ -146,12 +156,18 @@ func (ecp *ContactPointService) CreateContactPoint(ctx context.Context, orgID in
if contactPoint.UID == "" {
contactPoint.UID = util.GenerateShortUID()
}
jsonData, err := contactPoint.Settings.MarshalJSON()
if err != nil {
return apimodels.EmbeddedContactPoint{}, err
}
grafanaReceiver := &apimodels.PostableGrafanaReceiver{
UID: contactPoint.UID,
Name: contactPoint.Name,
Type: contactPoint.Type,
DisableResolveMessage: contactPoint.DisableResolveMessage,
Settings: contactPoint.Settings,
Settings: jsonData,
SecureSettings: extractedSecrets,
}
@ -260,12 +276,17 @@ func (ecp *ContactPointService) UpdateContactPoint(ctx context.Context, orgID in
}
extractedSecrets[k] = encryptedValue
}
jsonData, err := contactPoint.Settings.MarshalJSON()
if err != nil {
return err
}
mergedReceiver := &apimodels.PostableGrafanaReceiver{
UID: contactPoint.UID,
Name: contactPoint.Name,
Type: contactPoint.Type,
DisableResolveMessage: contactPoint.DisableResolveMessage,
Settings: contactPoint.Settings,
Settings: jsonData,
SecureSettings: extractedSecrets,
}
// save to store

View File

@ -470,6 +470,10 @@ func (m *migration) validateAlertmanagerConfig(orgID int64, config *PostableUser
secureSettings[k] = d
}
data, err := gr.Settings.MarshalJSON()
if err != nil {
return err
}
var (
cfg = &channels.NotificationChannelConfig{
UID: gr.UID,
@ -477,10 +481,9 @@ func (m *migration) validateAlertmanagerConfig(orgID int64, config *PostableUser
Name: gr.Name,
Type: gr.Type,
DisableResolveMessage: gr.DisableResolveMessage,
Settings: gr.Settings,
Settings: data,
SecureSettings: secureSettings,
}
err error
)
// decryptFunc represents the legacy way of decrypting data. Before the migration, we don't need any new way,