Files
grafana/pkg/services/ngalert/notifier/alertmanager_test.go
T
Serge Zaitsev a95fb3a37c Chore: Omit integration tests if short test flag is passed (#108777)
* 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>
2025-07-28 13:38:54 +02:00

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)
}
})
}
}