a95fb3a37c
* omit integration tests if short test flag is passed * Update pkg/services/ngalert/models/receivers_test.go Co-authored-by: Matheus Macabu <macabu@users.noreply.github.com> * Update pkg/tests/api/alerting/api_ruler_test.go Co-authored-by: Matheus Macabu <macabu@users.noreply.github.com> * Update pkg/tests/api/alerting/api_ruler_test.go Co-authored-by: Matheus Macabu <macabu@users.noreply.github.com> * Update pkg/tests/api/alerting/api_ruler_test.go Co-authored-by: Matheus Macabu <macabu@users.noreply.github.com> * Update pkg/tests/api/alerting/api_ruler_test.go Co-authored-by: Matheus Macabu <macabu@users.noreply.github.com> * Update pkg/tests/api/alerting/api_ruler_test.go Co-authored-by: Matheus Macabu <macabu@users.noreply.github.com> * Update pkg/services/ngalert/models/receivers_test.go Co-authored-by: Matheus Macabu <macabu@users.noreply.github.com> * Update pkg/cmd/grafana-cli/commands/datamigrations/to_unified_storage_test.go Co-authored-by: Matheus Macabu <macabu@users.noreply.github.com> * Update pkg/services/ngalert/models/receivers_test.go Co-authored-by: Matheus Macabu <macabu@users.noreply.github.com> * fix the rest * false positive --------- Co-authored-by: Matheus Macabu <macabu@users.noreply.github.com>
263 lines
7.4 KiB
Go
263 lines
7.4 KiB
Go
package notifier
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/prometheus/alertmanager/config"
|
|
"github.com/prometheus/alertmanager/pkg/labels"
|
|
"github.com/prometheus/client_golang/prometheus"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/grafana/grafana/pkg/infra/db"
|
|
"github.com/grafana/grafana/pkg/infra/log"
|
|
"github.com/grafana/grafana/pkg/services/dashboards"
|
|
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
|
"github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
|
|
"github.com/grafana/grafana/pkg/services/ngalert/metrics"
|
|
"github.com/grafana/grafana/pkg/services/ngalert/store"
|
|
"github.com/grafana/grafana/pkg/services/ngalert/tests/fakes"
|
|
"github.com/grafana/grafana/pkg/services/secrets/database"
|
|
secretsManager "github.com/grafana/grafana/pkg/services/secrets/manager"
|
|
"github.com/grafana/grafana/pkg/setting"
|
|
"github.com/grafana/grafana/pkg/tests/testsuite"
|
|
)
|
|
|
|
func TestMain(m *testing.M) {
|
|
testsuite.Run(m)
|
|
}
|
|
|
|
func setupAMTest(t *testing.T) *alertmanager {
|
|
dir := t.TempDir()
|
|
cfg := &setting.Cfg{
|
|
DataPath: dir,
|
|
AppURL: "http://localhost:9093",
|
|
}
|
|
|
|
l := log.New("alertmanager-test")
|
|
|
|
m := metrics.NewAlertmanagerMetrics(prometheus.NewRegistry(), l)
|
|
sqlStore := db.InitTestDB(t)
|
|
s := &store.DBstore{
|
|
Cfg: setting.UnifiedAlertingSettings{
|
|
BaseInterval: 10 * time.Second,
|
|
DefaultRuleEvaluationInterval: time.Minute,
|
|
},
|
|
SQLStore: sqlStore,
|
|
Logger: l,
|
|
DashboardService: dashboards.NewFakeDashboardService(t),
|
|
}
|
|
|
|
kvStore := fakes.NewFakeKVStore(t)
|
|
secretsService := secretsManager.SetupTestService(t, database.ProvideSecretsStore(sqlStore))
|
|
decryptFn := secretsService.GetDecryptedValue
|
|
|
|
orgID := 1
|
|
stateStore := NewFileStore(int64(orgID), kvStore)
|
|
crypto := NewCrypto(secretsService, s, l)
|
|
|
|
am, err := NewAlertmanager(context.Background(), 1, cfg, s, stateStore, &NilPeer{}, decryptFn, nil, m, featuremgmt.WithFeatures(), crypto, nil)
|
|
require.NoError(t, err)
|
|
return am
|
|
}
|
|
|
|
func TestIntegrationAlertmanager_newAlertmanager(t *testing.T) {
|
|
if testing.Short() {
|
|
t.Skip("skipping integration test in short mode")
|
|
}
|
|
am := setupAMTest(t)
|
|
require.False(t, am.Ready())
|
|
}
|
|
|
|
func TestAlertmanager_SaveAndApplyConfig_WithExternalSecrets(t *testing.T) {
|
|
am := setupAMTest(t)
|
|
|
|
cfg := &definitions.PostableUserConfig{
|
|
AlertmanagerConfig: definitions.PostableApiAlertingConfig{
|
|
Config: definitions.Config{
|
|
Route: &definitions.Route{
|
|
Receiver: "default-receiver",
|
|
},
|
|
},
|
|
Receivers: []*definitions.PostableApiReceiver{
|
|
{
|
|
Receiver: config.Receiver{Name: "default-receiver"},
|
|
},
|
|
},
|
|
},
|
|
ExtraConfigs: []definitions.ExtraConfiguration{
|
|
{
|
|
Identifier: "external-prometheus",
|
|
MergeMatchers: []*labels.Matcher{{Type: labels.MatchEqual, Name: "cluster", Value: "prod"}},
|
|
AlertmanagerConfig: `
|
|
route:
|
|
receiver: webhook-receiver
|
|
receivers:
|
|
- name: webhook-receiver
|
|
webhook_configs:
|
|
- url: 'https://webhook.example.com/alerts'
|
|
http_config:
|
|
basic_auth:
|
|
username: 'admin'
|
|
password: 'super-secret-password'
|
|
- url: 'https://slack.com/webhook/ABC123'
|
|
send_resolved: true
|
|
- name: email-receiver
|
|
email_configs:
|
|
- to: 'alerts@example.com'
|
|
from: 'grafana@example.com'
|
|
smarthost: 'smtp.gmail.com:587'
|
|
auth_username: 'grafana@example.com'
|
|
auth_password: 'another-secret-password'`,
|
|
},
|
|
},
|
|
}
|
|
|
|
err := am.SaveAndApplyConfig(context.Background(), cfg)
|
|
require.NoError(t, err)
|
|
|
|
savedConfig, err := am.Store.GetLatestAlertmanagerConfiguration(context.Background(), am.Base.TenantID())
|
|
require.NoError(t, err)
|
|
|
|
// Verify secrets are encrypted in stored config
|
|
var savedUserConfig definitions.PostableUserConfig
|
|
err = json.Unmarshal([]byte(savedConfig.AlertmanagerConfiguration), &savedUserConfig)
|
|
require.NoError(t, err)
|
|
|
|
require.Len(t, savedUserConfig.ExtraConfigs, 1)
|
|
extraConfig := savedUserConfig.ExtraConfigs[0]
|
|
|
|
require.Equal(t, "external-prometheus", extraConfig.Identifier)
|
|
require.NotContains(t, extraConfig.AlertmanagerConfig, "super-secret-password")
|
|
require.NotContains(t, extraConfig.AlertmanagerConfig, "another-secret-password")
|
|
require.NotContains(t, extraConfig.AlertmanagerConfig, "ABC123")
|
|
|
|
// Apply the saved configuration again and check that it is applied without errors
|
|
err = am.ApplyConfig(context.Background(), savedConfig)
|
|
require.NoError(t, err)
|
|
require.True(t, am.Ready())
|
|
}
|
|
|
|
func TestAlertmanager_ApplyConfig(t *testing.T) {
|
|
basicConfig := func() definitions.PostableApiAlertingConfig {
|
|
return definitions.PostableApiAlertingConfig{
|
|
Config: definitions.Config{
|
|
Route: &definitions.Route{
|
|
Receiver: "default-receiver",
|
|
ObjectMatchers: definitions.ObjectMatchers{
|
|
&labels.Matcher{
|
|
Type: labels.MatchEqual,
|
|
Name: "__grafana_autogenerated__",
|
|
Value: "true",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
Receivers: []*definitions.PostableApiReceiver{
|
|
{
|
|
Receiver: config.Receiver{
|
|
Name: "default-receiver",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
testCases := []struct {
|
|
name string
|
|
config *definitions.PostableUserConfig
|
|
expectedError string
|
|
skipInvalid bool
|
|
}{
|
|
{
|
|
name: "basic config",
|
|
config: &definitions.PostableUserConfig{
|
|
AlertmanagerConfig: basicConfig(),
|
|
TemplateFiles: map[string]string{
|
|
"grafana-template": "{{ define \"grafana.title\" }}Alert{{ end }}",
|
|
},
|
|
},
|
|
skipInvalid: false,
|
|
},
|
|
{
|
|
name: "with mimir config",
|
|
config: &definitions.PostableUserConfig{
|
|
AlertmanagerConfig: basicConfig(),
|
|
TemplateFiles: map[string]string{
|
|
"grafana-template": "{{ define \"grafana.title\" }}Grafana Alert{{ end }}",
|
|
},
|
|
ExtraConfigs: []definitions.ExtraConfiguration{
|
|
{
|
|
Identifier: "mimir-prod",
|
|
MergeMatchers: config.Matchers{
|
|
{
|
|
Type: labels.MatchEqual,
|
|
Name: "__mimir__",
|
|
Value: "true",
|
|
},
|
|
},
|
|
TemplateFiles: map[string]string{
|
|
"mimir-template": "{{ define \"mimir.title\" }}Mimir Alert{{ end }}",
|
|
},
|
|
AlertmanagerConfig: `route:
|
|
receiver: mimir-webhook
|
|
group_by:
|
|
- alertname
|
|
- cluster
|
|
receivers:
|
|
- name: mimir-webhook
|
|
webhook_configs:
|
|
- url: https://webhook.example.com/alerts
|
|
send_resolved: true
|
|
http_config: {}`,
|
|
},
|
|
},
|
|
},
|
|
skipInvalid: false,
|
|
},
|
|
{
|
|
name: "invalid config fails",
|
|
config: &definitions.PostableUserConfig{
|
|
AlertmanagerConfig: basicConfig(),
|
|
ExtraConfigs: []definitions.ExtraConfiguration{
|
|
{
|
|
Identifier: "", // invalid: empty identifier
|
|
MergeMatchers: config.Matchers{},
|
|
AlertmanagerConfig: `route:
|
|
receiver: test-receiver
|
|
receivers:
|
|
- name: test-receiver`,
|
|
},
|
|
},
|
|
},
|
|
expectedError: "failed to get full alertmanager configuration",
|
|
skipInvalid: false,
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
am := setupAMTest(t)
|
|
ctx := context.Background()
|
|
|
|
err := am.SaveAndApplyConfig(ctx, tc.config)
|
|
|
|
if tc.expectedError != "" {
|
|
require.Error(t, err)
|
|
require.ErrorContains(t, err, tc.expectedError)
|
|
} else {
|
|
require.NoError(t, err)
|
|
|
|
templateDefs := tc.config.GetMergedTemplateDefinitions()
|
|
expectedTemplateCount := len(tc.config.TemplateFiles)
|
|
if len(tc.config.ExtraConfigs) > 0 {
|
|
expectedTemplateCount += len(tc.config.ExtraConfigs[0].TemplateFiles)
|
|
}
|
|
require.Len(t, templateDefs, expectedTemplateCount)
|
|
}
|
|
})
|
|
}
|
|
}
|