mirror of
https://github.com/grafana/grafana.git
synced 2025-02-14 01:23:32 -06:00
Alerting: Use interfaces for the Alertmanager (#73900)
This commit is contained in:
parent
f8026463a8
commit
93b9f9b537
@ -12,7 +12,6 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/datasourceproxy"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
apimodels "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/backtesting"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/eval"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/metrics"
|
||||
@ -34,28 +33,6 @@ type ExternalAlertmanagerProvider interface {
|
||||
DroppedAlertmanagersFor(orgID int64) []*url.URL
|
||||
}
|
||||
|
||||
type Alertmanager interface {
|
||||
// Configuration
|
||||
SaveAndApplyConfig(ctx context.Context, config *apimodels.PostableUserConfig) error
|
||||
SaveAndApplyDefaultConfig(ctx context.Context) error
|
||||
GetStatus() apimodels.GettableStatus
|
||||
|
||||
// Silences
|
||||
CreateSilence(ps *apimodels.PostableSilence) (string, error)
|
||||
DeleteSilence(silenceID string) error
|
||||
GetSilence(silenceID string) (apimodels.GettableSilence, error)
|
||||
ListSilences(filter []string) (apimodels.GettableSilences, error)
|
||||
|
||||
// Alerts
|
||||
GetAlerts(active, silenced, inhibited bool, filter []string, receiver string) (apimodels.GettableAlerts, error)
|
||||
GetAlertGroups(active, silenced, inhibited bool, filter []string, receiver string) (apimodels.AlertGroups, error)
|
||||
|
||||
// Receivers
|
||||
GetReceivers(ctx context.Context) []apimodels.Receiver
|
||||
TestReceivers(ctx context.Context, c apimodels.TestReceiversConfigBodyParams) (*notifier.TestReceiversResult, error)
|
||||
TestTemplate(ctx context.Context, c apimodels.TestTemplatesConfigBodyParams) (*notifier.TestTemplatesResults, error)
|
||||
}
|
||||
|
||||
type AlertingStore interface {
|
||||
GetLatestAlertmanagerConfiguration(ctx context.Context, query *models.GetLatestAlertmanagerConfigurationQuery) (*models.AlertConfiguration, error)
|
||||
}
|
||||
|
@ -458,7 +458,7 @@ func newTestTemplateResult(res *notifier.TestTemplatesResults) apimodels.TestTem
|
||||
return apiRes
|
||||
}
|
||||
|
||||
func (srv AlertmanagerSrv) AlertmanagerFor(orgID int64) (Alertmanager, *response.NormalResponse) {
|
||||
func (srv AlertmanagerSrv) AlertmanagerFor(orgID int64) (notifier.Alertmanager, *response.NormalResponse) {
|
||||
am, err := srv.mam.AlertmanagerFor(orgID)
|
||||
if err == nil {
|
||||
return am, nil
|
||||
|
@ -231,7 +231,7 @@ func TestAlertmanagerConfig(t *testing.T) {
|
||||
|
||||
am, err := sut.mam.AlertmanagerFor(1)
|
||||
require.NoError(t, err)
|
||||
hash := am.Base.ConfigHash()
|
||||
hash := am.ConfigHash()
|
||||
|
||||
getResponse := sut.RouteGetAlertingConfig(&rc)
|
||||
require.Equal(t, 200, getResponse.Status())
|
||||
@ -243,7 +243,7 @@ func TestAlertmanagerConfig(t *testing.T) {
|
||||
|
||||
am, err = sut.mam.AlertmanagerFor(1)
|
||||
require.NoError(t, err)
|
||||
newHash := am.Base.ConfigHash()
|
||||
newHash := am.ConfigHash()
|
||||
require.Equal(t, hash, newHash)
|
||||
})
|
||||
|
||||
|
@ -44,7 +44,7 @@ type AlertingStore interface {
|
||||
store.ImageStore
|
||||
}
|
||||
|
||||
type Alertmanager struct {
|
||||
type alertmanager struct {
|
||||
Base *alertingNotify.GrafanaAlertmanager
|
||||
logger log.Logger
|
||||
|
||||
@ -85,7 +85,7 @@ func (m maintenanceOptions) MaintenanceFunc(state alertingNotify.State) (int64,
|
||||
|
||||
func newAlertmanager(ctx context.Context, orgID int64, cfg *setting.Cfg, store AlertingStore, kvStore kvstore.KVStore,
|
||||
peer alertingNotify.ClusterPeer, decryptFn alertingNotify.GetDecryptedValueFn, ns notifications.Service,
|
||||
m *metrics.Alertmanager) (*Alertmanager, error) {
|
||||
m *metrics.Alertmanager) (*alertmanager, error) {
|
||||
workingPath := filepath.Join(cfg.DataPath, workingDir, strconv.Itoa(int(orgID)))
|
||||
fileStore := NewFileStore(orgID, kvStore, workingPath)
|
||||
|
||||
@ -133,7 +133,7 @@ func newAlertmanager(ctx context.Context, orgID int64, cfg *setting.Cfg, store A
|
||||
return nil, err
|
||||
}
|
||||
|
||||
am := &Alertmanager{
|
||||
am := &alertmanager{
|
||||
Base: gam,
|
||||
ConfigMetrics: m.AlertmanagerConfigMetrics,
|
||||
Settings: cfg,
|
||||
@ -148,20 +148,20 @@ func newAlertmanager(ctx context.Context, orgID int64, cfg *setting.Cfg, store A
|
||||
return am, nil
|
||||
}
|
||||
|
||||
func (am *Alertmanager) Ready() bool {
|
||||
func (am *alertmanager) Ready() bool {
|
||||
// We consider AM as ready only when the config has been
|
||||
// applied at least once successfully. Until then, some objects
|
||||
// can still be nil.
|
||||
return am.Base.Ready()
|
||||
}
|
||||
|
||||
func (am *Alertmanager) StopAndWait() {
|
||||
func (am *alertmanager) StopAndWait() {
|
||||
am.Base.StopAndWait()
|
||||
}
|
||||
|
||||
// SaveAndApplyDefaultConfig saves the default configuration to the database and applies it to the Alertmanager.
|
||||
// It rolls back the save if we fail to apply the configuration.
|
||||
func (am *Alertmanager) SaveAndApplyDefaultConfig(ctx context.Context) error {
|
||||
func (am *alertmanager) SaveAndApplyDefaultConfig(ctx context.Context) error {
|
||||
var outerErr error
|
||||
am.Base.WithLock(func() {
|
||||
cmd := &ngmodels.SaveAlertmanagerConfigurationCmd{
|
||||
@ -193,7 +193,7 @@ func (am *Alertmanager) SaveAndApplyDefaultConfig(ctx context.Context) error {
|
||||
|
||||
// SaveAndApplyConfig saves the configuration the database and applies the configuration to the Alertmanager.
|
||||
// It rollbacks the save if we fail to apply the configuration.
|
||||
func (am *Alertmanager) SaveAndApplyConfig(ctx context.Context, cfg *apimodels.PostableUserConfig) error {
|
||||
func (am *alertmanager) SaveAndApplyConfig(ctx context.Context, cfg *apimodels.PostableUserConfig) error {
|
||||
rawConfig, err := json.Marshal(&cfg)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to serialize to the Alertmanager configuration: %w", err)
|
||||
@ -222,7 +222,7 @@ func (am *Alertmanager) SaveAndApplyConfig(ctx context.Context, cfg *apimodels.P
|
||||
}
|
||||
|
||||
// ApplyConfig applies the configuration to the Alertmanager.
|
||||
func (am *Alertmanager) ApplyConfig(ctx context.Context, dbCfg *ngmodels.AlertConfiguration) error {
|
||||
func (am *alertmanager) ApplyConfig(ctx context.Context, dbCfg *ngmodels.AlertConfiguration) error {
|
||||
var err error
|
||||
cfg, err := Load([]byte(dbCfg.AlertmanagerConfiguration))
|
||||
if err != nil {
|
||||
@ -247,7 +247,7 @@ type AggregateMatchersUsage struct {
|
||||
ObjectMatchers int
|
||||
}
|
||||
|
||||
func (am *Alertmanager) updateConfigMetrics(cfg *apimodels.PostableUserConfig) {
|
||||
func (am *alertmanager) updateConfigMetrics(cfg *apimodels.PostableUserConfig) {
|
||||
var amu AggregateMatchersUsage
|
||||
am.aggregateRouteMatchers(cfg.AlertmanagerConfig.Route, &amu)
|
||||
am.aggregateInhibitMatchers(cfg.AlertmanagerConfig.InhibitRules, &amu)
|
||||
@ -257,7 +257,7 @@ func (am *Alertmanager) updateConfigMetrics(cfg *apimodels.PostableUserConfig) {
|
||||
am.ConfigMetrics.ObjectMatchers.Set(float64(amu.ObjectMatchers))
|
||||
}
|
||||
|
||||
func (am *Alertmanager) aggregateRouteMatchers(r *apimodels.Route, amu *AggregateMatchersUsage) {
|
||||
func (am *alertmanager) aggregateRouteMatchers(r *apimodels.Route, amu *AggregateMatchersUsage) {
|
||||
amu.Matchers += len(r.Matchers)
|
||||
amu.MatchRE += len(r.MatchRE)
|
||||
amu.Match += len(r.Match)
|
||||
@ -267,7 +267,7 @@ func (am *Alertmanager) aggregateRouteMatchers(r *apimodels.Route, amu *Aggregat
|
||||
}
|
||||
}
|
||||
|
||||
func (am *Alertmanager) aggregateInhibitMatchers(rules []config.InhibitRule, amu *AggregateMatchersUsage) {
|
||||
func (am *alertmanager) aggregateInhibitMatchers(rules []config.InhibitRule, amu *AggregateMatchersUsage) {
|
||||
for _, r := range rules {
|
||||
amu.Matchers += len(r.SourceMatchers)
|
||||
amu.Matchers += len(r.TargetMatchers)
|
||||
@ -281,7 +281,7 @@ func (am *Alertmanager) aggregateInhibitMatchers(rules []config.InhibitRule, amu
|
||||
// applyConfig applies a new configuration by re-initializing all components using the configuration provided.
|
||||
// It returns a boolean indicating whether the user config was changed and an error.
|
||||
// It is not safe to call concurrently.
|
||||
func (am *Alertmanager) applyConfig(cfg *apimodels.PostableUserConfig, rawConfig []byte) (bool, error) {
|
||||
func (am *alertmanager) applyConfig(cfg *apimodels.PostableUserConfig, rawConfig []byte) (bool, error) {
|
||||
// First, let's make sure this config is not already loaded
|
||||
var amConfigChanged bool
|
||||
if rawConfig == nil {
|
||||
@ -331,7 +331,7 @@ func (am *Alertmanager) applyConfig(cfg *apimodels.PostableUserConfig, rawConfig
|
||||
}
|
||||
|
||||
// applyAndMarkConfig applies a configuration and marks it as applied if no errors occur.
|
||||
func (am *Alertmanager) applyAndMarkConfig(ctx context.Context, hash string, cfg *apimodels.PostableUserConfig, rawConfig []byte) error {
|
||||
func (am *alertmanager) applyAndMarkConfig(ctx context.Context, hash string, cfg *apimodels.PostableUserConfig, rawConfig []byte) error {
|
||||
configChanged, err := am.applyConfig(cfg, rawConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -348,12 +348,12 @@ func (am *Alertmanager) applyAndMarkConfig(ctx context.Context, hash string, cfg
|
||||
return nil
|
||||
}
|
||||
|
||||
func (am *Alertmanager) AppURL() string {
|
||||
func (am *alertmanager) AppURL() string {
|
||||
return am.Settings.AppURL
|
||||
}
|
||||
|
||||
// buildReceiverIntegrations builds a list of integration notifiers off of a receiver config.
|
||||
func (am *Alertmanager) buildReceiverIntegrations(receiver *alertingNotify.APIReceiver, tmpl *alertingTemplates.Template) ([]*alertingNotify.Integration, error) {
|
||||
func (am *alertmanager) buildReceiverIntegrations(receiver *alertingNotify.APIReceiver, tmpl *alertingTemplates.Template) ([]*alertingNotify.Integration, error) {
|
||||
receiverCfg, err := alertingNotify.BuildReceiverConfiguration(context.Background(), receiver, am.decryptFn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -381,7 +381,7 @@ func (am *Alertmanager) buildReceiverIntegrations(receiver *alertingNotify.APIRe
|
||||
}
|
||||
|
||||
// PutAlerts receives the alerts and then sends them through the corresponding route based on whenever the alert has a receiver embedded or not
|
||||
func (am *Alertmanager) PutAlerts(postableAlerts apimodels.PostableAlerts) error {
|
||||
func (am *alertmanager) PutAlerts(postableAlerts apimodels.PostableAlerts) error {
|
||||
alerts := make(alertingNotify.PostableAlerts, 0, len(postableAlerts.PostableAlerts))
|
||||
for _, pa := range postableAlerts.PostableAlerts {
|
||||
alerts = append(alerts, &alertingNotify.PostableAlert{
|
||||
@ -395,6 +395,18 @@ func (am *Alertmanager) PutAlerts(postableAlerts apimodels.PostableAlerts) error
|
||||
return am.Base.PutAlerts(alerts)
|
||||
}
|
||||
|
||||
func (am *alertmanager) ConfigHash() [16]byte {
|
||||
return am.Base.ConfigHash()
|
||||
}
|
||||
|
||||
func (am *alertmanager) OrgID() int64 {
|
||||
return am.orgID
|
||||
}
|
||||
|
||||
func (am *alertmanager) FileStore() *FileStore {
|
||||
return am.fileStore
|
||||
}
|
||||
|
||||
// AlertValidationError is the error capturing the validation errors
|
||||
// faced on the alerts.
|
||||
type AlertValidationError struct {
|
||||
|
@ -18,7 +18,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
func setupAMTest(t *testing.T) *Alertmanager {
|
||||
func setupAMTest(t *testing.T) *alertmanager {
|
||||
dir := t.TempDir()
|
||||
cfg := &setting.Cfg{
|
||||
DataPath: dir,
|
||||
|
@ -4,10 +4,10 @@ import (
|
||||
alertingNotify "github.com/grafana/alerting/notify"
|
||||
)
|
||||
|
||||
func (am *Alertmanager) GetAlerts(active, silenced, inhibited bool, filter []string, receivers string) (alertingNotify.GettableAlerts, error) {
|
||||
func (am *alertmanager) GetAlerts(active, silenced, inhibited bool, filter []string, receivers string) (alertingNotify.GettableAlerts, error) {
|
||||
return am.Base.GetAlerts(active, silenced, inhibited, filter, receivers)
|
||||
}
|
||||
|
||||
func (am *Alertmanager) GetAlertGroups(active, silenced, inhibited bool, filter []string, receivers string) (alertingNotify.AlertGroups, error) {
|
||||
func (am *alertmanager) GetAlertGroups(active, silenced, inhibited bool, filter []string, receivers string) (alertingNotify.AlertGroups, error) {
|
||||
return am.Base.GetAlertGroups(active, silenced, inhibited, filter, receivers)
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/kvstore"
|
||||
"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/metrics"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/store"
|
||||
@ -29,12 +30,43 @@ var (
|
||||
ErrAlertmanagerNotReady = fmt.Errorf("Alertmanager is not ready yet")
|
||||
)
|
||||
|
||||
type Alertmanager interface {
|
||||
// Configuration
|
||||
SaveAndApplyConfig(ctx context.Context, config *apimodels.PostableUserConfig) error
|
||||
SaveAndApplyDefaultConfig(ctx context.Context) error
|
||||
GetStatus() apimodels.GettableStatus
|
||||
|
||||
// Silences
|
||||
CreateSilence(*apimodels.PostableSilence) (string, error)
|
||||
DeleteSilence(string) error
|
||||
GetSilence(string) (apimodels.GettableSilence, error)
|
||||
ListSilences([]string) (apimodels.GettableSilences, error)
|
||||
|
||||
// Alerts
|
||||
GetAlerts(active, silenced, inhibited bool, filter []string, receiver string) (apimodels.GettableAlerts, error)
|
||||
GetAlertGroups(active, silenced, inhibited bool, filter []string, receiver string) (apimodels.AlertGroups, error)
|
||||
PutAlerts(postableAlerts apimodels.PostableAlerts) error
|
||||
|
||||
// Receivers
|
||||
GetReceivers(ctx context.Context) []apimodels.Receiver
|
||||
TestReceivers(ctx context.Context, c apimodels.TestReceiversConfigBodyParams) (*TestReceiversResult, error)
|
||||
TestTemplate(ctx context.Context, c apimodels.TestTemplatesConfigBodyParams) (*TestTemplatesResults, error)
|
||||
ApplyConfig(context.Context, *models.AlertConfiguration) error
|
||||
|
||||
// State
|
||||
StopAndWait()
|
||||
Ready() bool
|
||||
FileStore() *FileStore
|
||||
OrgID() int64
|
||||
ConfigHash() [16]byte
|
||||
}
|
||||
|
||||
type MultiOrgAlertmanager struct {
|
||||
Crypto Crypto
|
||||
ProvStore provisioningStore
|
||||
|
||||
alertmanagersMtx sync.RWMutex
|
||||
alertmanagers map[int64]*Alertmanager
|
||||
alertmanagers map[int64]Alertmanager
|
||||
|
||||
settings *setting.Cfg
|
||||
logger log.Logger
|
||||
@ -63,7 +95,7 @@ func NewMultiOrgAlertmanager(cfg *setting.Cfg, configStore AlertingStore, orgSto
|
||||
|
||||
logger: l,
|
||||
settings: cfg,
|
||||
alertmanagers: map[int64]*Alertmanager{},
|
||||
alertmanagers: map[int64]Alertmanager{},
|
||||
configStore: configStore,
|
||||
orgStore: orgStore,
|
||||
kvStore: kvStore,
|
||||
@ -244,7 +276,7 @@ func (moa *MultiOrgAlertmanager) SyncAlertmanagersForOrgs(ctx context.Context, o
|
||||
moa.alertmanagers[orgID] = alertmanager
|
||||
}
|
||||
|
||||
amsToStop := map[int64]*Alertmanager{}
|
||||
amsToStop := map[int64]Alertmanager{}
|
||||
for orgId, am := range moa.alertmanagers {
|
||||
if _, exists := orgsFound[orgId]; !exists {
|
||||
amsToStop[orgId] = am
|
||||
@ -261,7 +293,7 @@ func (moa *MultiOrgAlertmanager) SyncAlertmanagersForOrgs(ctx context.Context, o
|
||||
am.StopAndWait()
|
||||
moa.logger.Info("Stopped Alertmanager", "org", orgID)
|
||||
// Cleanup all the remaining resources from this alertmanager.
|
||||
am.fileStore.CleanUp()
|
||||
am.FileStore().CleanUp()
|
||||
}
|
||||
|
||||
// We look for orphan directories and remove them. Orphan directories can
|
||||
@ -348,7 +380,7 @@ func (moa *MultiOrgAlertmanager) StopAndWait() {
|
||||
// AlertmanagerFor returns the Alertmanager instance for the organization provided.
|
||||
// When the organization does not have an active Alertmanager, it returns a ErrNoAlertmanagerForOrg.
|
||||
// When the Alertmanager of the organization is not ready, it returns a ErrAlertmanagerNotReady.
|
||||
func (moa *MultiOrgAlertmanager) AlertmanagerFor(orgID int64) (*Alertmanager, error) {
|
||||
func (moa *MultiOrgAlertmanager) AlertmanagerFor(orgID int64) (Alertmanager, error) {
|
||||
moa.alertmanagersMtx.RLock()
|
||||
defer moa.alertmanagersMtx.RUnlock()
|
||||
|
||||
|
@ -285,9 +285,9 @@ func TestMultiOrgAlertmanager_AlertmanagerFor(t *testing.T) {
|
||||
{
|
||||
am, err := mam.AlertmanagerFor(2)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, *am.GetStatus().VersionInfo.Version, "N/A")
|
||||
require.Equal(t, am.orgID, int64(2))
|
||||
require.NotNil(t, am.Base.ConfigHash())
|
||||
require.Equal(t, "N/A", *am.GetStatus().VersionInfo.Version)
|
||||
require.Equal(t, int64(2), am.OrgID())
|
||||
require.NotNil(t, am.ConfigHash())
|
||||
}
|
||||
|
||||
// Let's now remove the previous queried organization.
|
||||
|
@ -32,7 +32,7 @@ type TestReceiverConfigResult struct {
|
||||
Error error
|
||||
}
|
||||
|
||||
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))
|
||||
for _, r := range c.Receivers {
|
||||
integrations := make([]*alertingNotify.GrafanaIntegrationConfig, 0, len(r.GrafanaManagedReceivers))
|
||||
@ -91,7 +91,7 @@ func (am *Alertmanager) TestReceivers(ctx context.Context, c apimodels.TestRecei
|
||||
}, err
|
||||
}
|
||||
|
||||
func (am *Alertmanager) GetReceivers(_ context.Context) []apimodels.Receiver {
|
||||
func (am *alertmanager) GetReceivers(_ context.Context) []apimodels.Receiver {
|
||||
apiReceivers := make([]apimodels.Receiver, 0, len(am.Base.GetReceivers()))
|
||||
for _, rcv := range am.Base.GetReceivers() {
|
||||
// Build integrations slice for each receiver.
|
||||
|
@ -4,18 +4,18 @@ import (
|
||||
alertingNotify "github.com/grafana/alerting/notify"
|
||||
)
|
||||
|
||||
func (am *Alertmanager) ListSilences(filter []string) (alertingNotify.GettableSilences, error) {
|
||||
func (am *alertmanager) ListSilences(filter []string) (alertingNotify.GettableSilences, error) {
|
||||
return am.Base.ListSilences(filter)
|
||||
}
|
||||
|
||||
func (am *Alertmanager) GetSilence(silenceID string) (alertingNotify.GettableSilence, error) {
|
||||
func (am *alertmanager) GetSilence(silenceID string) (alertingNotify.GettableSilence, error) {
|
||||
return am.Base.GetSilence(silenceID)
|
||||
}
|
||||
|
||||
func (am *Alertmanager) CreateSilence(ps *alertingNotify.PostableSilence) (string, error) {
|
||||
func (am *alertmanager) CreateSilence(ps *alertingNotify.PostableSilence) (string, error) {
|
||||
return am.Base.CreateSilence(ps)
|
||||
}
|
||||
|
||||
func (am *Alertmanager) DeleteSilence(silenceID string) error {
|
||||
func (am *alertmanager) DeleteSilence(silenceID string) error {
|
||||
return am.Base.DeleteSilence(silenceID)
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import (
|
||||
)
|
||||
|
||||
// TODO: We no longer do apimodels at this layer, move it to the API.
|
||||
func (am *Alertmanager) GetStatus() apimodels.GettableStatus {
|
||||
func (am *alertmanager) GetStatus() apimodels.GettableStatus {
|
||||
config := &apimodels.PostableUserConfig{}
|
||||
status := am.Base.GetStatus()
|
||||
if status == nil {
|
||||
|
@ -29,7 +29,7 @@ var (
|
||||
|
||||
// TestTemplate tests the given template string against the given alerts. Existing templates are used to provide context for the test.
|
||||
// If an existing template of the same filename as the one being tested is found, it will not be used as context.
|
||||
func (am *Alertmanager) TestTemplate(ctx context.Context, c apimodels.TestTemplatesConfigBodyParams) (*TestTemplatesResults, error) {
|
||||
func (am *alertmanager) TestTemplate(ctx context.Context, c apimodels.TestTemplatesConfigBodyParams) (*TestTemplatesResults, error) {
|
||||
for _, alert := range c.Alerts {
|
||||
addDefaultLabelsAndAnnotations(alert)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user