Altering: validate that the mute time intervals exist when updating routing tree (#51573)

* validate that the mute time intervals exist when updating routing tree

* run lint

* add tests
pull/51677/head^2
Jean-Philippe Quéméner 3 years ago committed by GitHub
parent b9c7eb1380
commit 4a76436be2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 15
      pkg/services/ngalert/api/tooling/definitions/alertmanager_validation.go
  2. 9
      pkg/services/ngalert/provisioning/notification_policies.go
  3. 79
      pkg/services/ngalert/provisioning/notification_policies_test.go

@ -114,6 +114,21 @@ func (r *Route) ValidateReceivers(receivers map[string]struct{}) error {
return nil
}
func (r *Route) ValidateMuteTimes(muteTimes map[string]struct{}) error {
for _, name := range r.MuteTimeIntervals {
if _, exists := muteTimes[name]; !exists {
return fmt.Errorf("mute time interval '%s' does not exist", name)
}
}
for _, child := range r.Routes {
err := child.ValidateMuteTimes(muteTimes)
if err != nil {
return err
}
}
return nil
}
func (mt *MuteTimeInterval) Validate() error {
s, err := yaml.Marshal(mt.MuteTimeInterval)
if err != nil {

@ -76,6 +76,15 @@ func (nps *NotificationPolicyService) UpdatePolicyTree(ctx context.Context, orgI
return fmt.Errorf("%w: %s", ErrValidation, err.Error())
}
muteTimes := map[string]struct{}{}
for _, mt := range revision.cfg.AlertmanagerConfig.MuteTimeIntervals {
muteTimes[mt.Name] = struct{}{}
}
err = tree.ValidateMuteTimes(muteTimes)
if err != nil {
return fmt.Errorf("%w: %s", ErrValidation, err.Error())
}
revision.cfg.AlertmanagerConfig.Config.Route = &tree
serialized, err := serializeAlertmanagerConfig(*revision.cfg)

@ -8,8 +8,9 @@ import (
"github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
"github.com/grafana/grafana/pkg/services/ngalert/models"
"github.com/prometheus/alertmanager/config"
"github.com/prometheus/alertmanager/timeinterval"
"github.com/prometheus/common/model"
mock "github.com/stretchr/testify/mock"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
)
@ -23,6 +24,82 @@ func TestNotificationPolicyService(t *testing.T) {
require.Equal(t, "grafana-default-email", tree.Receiver)
})
t.Run("error if referenced mute time interval is not existing", func(t *testing.T) {
sut := createNotificationPolicyServiceSut()
sut.amStore = &MockAMConfigStore{}
sut.amStore.(*MockAMConfigStore).On("GetLatestAlertmanagerConfiguration", mock.Anything, mock.Anything).
Return(
func(ctx context.Context, query *models.GetLatestAlertmanagerConfigurationQuery) error {
cfg, _ := deserializeAlertmanagerConfig([]byte(defaultConfig))
mti := config.MuteTimeInterval{
Name: "not-the-one-we-need",
TimeIntervals: []timeinterval.TimeInterval{},
}
cfg.AlertmanagerConfig.MuteTimeIntervals = append(cfg.AlertmanagerConfig.MuteTimeIntervals, mti)
cfg.AlertmanagerConfig.Receivers = append(cfg.AlertmanagerConfig.Receivers,
&definitions.PostableApiReceiver{
Receiver: config.Receiver{
// default one from createTestRoutingTree()
Name: "a new receiver",
},
})
data, _ := serializeAlertmanagerConfig(*cfg)
query.Result = &models.AlertConfiguration{
AlertmanagerConfiguration: string(data),
}
return nil
})
sut.amStore.(*MockAMConfigStore).EXPECT().
UpdateAlertmanagerConfiguration(mock.Anything, mock.Anything).
Return(nil)
newRoute := createTestRoutingTree()
newRoute.Routes = append(newRoute.Routes, &definitions.Route{
Receiver: "a new receiver",
MuteTimeIntervals: []string{"not-existing"},
})
err := sut.UpdatePolicyTree(context.Background(), 1, newRoute, models.ProvenanceNone)
require.Error(t, err)
})
t.Run("pass if referenced mute time interval is existing", func(t *testing.T) {
sut := createNotificationPolicyServiceSut()
sut.amStore = &MockAMConfigStore{}
sut.amStore.(*MockAMConfigStore).On("GetLatestAlertmanagerConfiguration", mock.Anything, mock.Anything).
Return(
func(ctx context.Context, query *models.GetLatestAlertmanagerConfigurationQuery) error {
cfg, _ := deserializeAlertmanagerConfig([]byte(defaultConfig))
mti := config.MuteTimeInterval{
Name: "existing",
TimeIntervals: []timeinterval.TimeInterval{},
}
cfg.AlertmanagerConfig.MuteTimeIntervals = append(cfg.AlertmanagerConfig.MuteTimeIntervals, mti)
cfg.AlertmanagerConfig.Receivers = append(cfg.AlertmanagerConfig.Receivers,
&definitions.PostableApiReceiver{
Receiver: config.Receiver{
// default one from createTestRoutingTree()
Name: "a new receiver",
},
})
data, _ := serializeAlertmanagerConfig(*cfg)
query.Result = &models.AlertConfiguration{
AlertmanagerConfiguration: string(data),
}
return nil
})
sut.amStore.(*MockAMConfigStore).EXPECT().
UpdateAlertmanagerConfiguration(mock.Anything, mock.Anything).
Return(nil)
newRoute := createTestRoutingTree()
newRoute.Routes = append(newRoute.Routes, &definitions.Route{
Receiver: "a new receiver",
MuteTimeIntervals: []string{"existing"},
})
err := sut.UpdatePolicyTree(context.Background(), 1, newRoute, models.ProvenanceNone)
require.NoError(t, err)
})
t.Run("service stitches policy tree into org's AM config", func(t *testing.T) {
sut := createNotificationPolicyServiceSut()

Loading…
Cancel
Save