mirror of
https://github.com/grafana/grafana.git
synced 2025-09-25 17:04:10 +08:00
Alerting: Add method to reset notification policy tree back to the default (#51934)
* Define route and run codegen * Wire up HTTP layer * Update API layer and test fakes * Implement reset of policy tree * Implement service layer test and authorization bindings * API layer testing * Be more specific when injecting settings
This commit is contained in:
@ -40,6 +40,7 @@ type TemplateService interface {
|
|||||||
type NotificationPolicyService interface {
|
type NotificationPolicyService interface {
|
||||||
GetPolicyTree(ctx context.Context, orgID int64) (definitions.Route, error)
|
GetPolicyTree(ctx context.Context, orgID int64) (definitions.Route, error)
|
||||||
UpdatePolicyTree(ctx context.Context, orgID int64, tree definitions.Route, p alerting_models.Provenance) error
|
UpdatePolicyTree(ctx context.Context, orgID int64, tree definitions.Route, p alerting_models.Provenance) error
|
||||||
|
ResetPolicyTree(ctx context.Context, orgID int64) (definitions.Route, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type MuteTimingService interface {
|
type MuteTimingService interface {
|
||||||
@ -85,6 +86,14 @@ func (srv *ProvisioningSrv) RoutePutPolicyTree(c *models.ReqContext, tree defini
|
|||||||
return response.JSON(http.StatusAccepted, util.DynMap{"message": "policies updated"})
|
return response.JSON(http.StatusAccepted, util.DynMap{"message": "policies updated"})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (srv *ProvisioningSrv) RouteResetPolicyTree(c *models.ReqContext) response.Response {
|
||||||
|
tree, err := srv.policies.ResetPolicyTree(c.Req.Context(), c.OrgId)
|
||||||
|
if err != nil {
|
||||||
|
return ErrResp(http.StatusInternalServerError, err, "")
|
||||||
|
}
|
||||||
|
return response.JSON(http.StatusAccepted, tree)
|
||||||
|
}
|
||||||
|
|
||||||
func (srv *ProvisioningSrv) RouteGetContactPoints(c *models.ReqContext) response.Response {
|
func (srv *ProvisioningSrv) RouteGetContactPoints(c *models.ReqContext) response.Response {
|
||||||
cps, err := srv.contactPointService.GetContactPoints(c.Req.Context(), c.OrgId)
|
cps, err := srv.contactPointService.GetContactPoints(c.Req.Context(), c.OrgId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -44,6 +44,15 @@ func TestProvisioningApi(t *testing.T) {
|
|||||||
require.Equal(t, 202, response.Status())
|
require.Equal(t, 202, response.Status())
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("successful DELETE returns 202", func(t *testing.T) {
|
||||||
|
sut := createProvisioningSrvSut(t)
|
||||||
|
rc := createTestRequestCtx()
|
||||||
|
|
||||||
|
response := sut.RouteResetPolicyTree(&rc)
|
||||||
|
|
||||||
|
require.Equal(t, 202, response.Status())
|
||||||
|
})
|
||||||
|
|
||||||
t.Run("when new policy tree is invalid", func(t *testing.T) {
|
t.Run("when new policy tree is invalid", func(t *testing.T) {
|
||||||
t.Run("PUT returns 400", func(t *testing.T) {
|
t.Run("PUT returns 400", func(t *testing.T) {
|
||||||
sut := createProvisioningSrvSut(t)
|
sut := createProvisioningSrvSut(t)
|
||||||
@ -106,6 +115,18 @@ func TestProvisioningApi(t *testing.T) {
|
|||||||
require.NotEmpty(t, response.Body())
|
require.NotEmpty(t, response.Body())
|
||||||
require.Contains(t, string(response.Body()), "something went wrong")
|
require.Contains(t, string(response.Body()), "something went wrong")
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("DELETE returns 500", func(t *testing.T) {
|
||||||
|
sut := createProvisioningSrvSut(t)
|
||||||
|
sut.policies = &fakeFailingNotificationPolicyService{}
|
||||||
|
rc := createTestRequestCtx()
|
||||||
|
|
||||||
|
response := sut.RouteResetPolicyTree(&rc)
|
||||||
|
|
||||||
|
require.Equal(t, 500, response.Status())
|
||||||
|
require.NotEmpty(t, response.Body())
|
||||||
|
require.Contains(t, string(response.Body()), "something went wrong")
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -335,6 +356,11 @@ func (f *fakeNotificationPolicyService) UpdatePolicyTree(ctx context.Context, or
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *fakeNotificationPolicyService) ResetPolicyTree(ctx context.Context, orgID int64) (definitions.Route, error) {
|
||||||
|
f.tree = definitions.Route{} // TODO
|
||||||
|
return f.tree, nil
|
||||||
|
}
|
||||||
|
|
||||||
type fakeFailingNotificationPolicyService struct{}
|
type fakeFailingNotificationPolicyService struct{}
|
||||||
|
|
||||||
func (f *fakeFailingNotificationPolicyService) GetPolicyTree(ctx context.Context, orgID int64) (definitions.Route, error) {
|
func (f *fakeFailingNotificationPolicyService) GetPolicyTree(ctx context.Context, orgID int64) (definitions.Route, error) {
|
||||||
@ -345,6 +371,10 @@ func (f *fakeFailingNotificationPolicyService) UpdatePolicyTree(ctx context.Cont
|
|||||||
return fmt.Errorf("something went wrong")
|
return fmt.Errorf("something went wrong")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *fakeFailingNotificationPolicyService) ResetPolicyTree(ctx context.Context, orgID int64) (definitions.Route, error) {
|
||||||
|
return definitions.Route{}, fmt.Errorf("something went wrong")
|
||||||
|
}
|
||||||
|
|
||||||
type fakeRejectingNotificationPolicyService struct{}
|
type fakeRejectingNotificationPolicyService struct{}
|
||||||
|
|
||||||
func (f *fakeRejectingNotificationPolicyService) GetPolicyTree(ctx context.Context, orgID int64) (definitions.Route, error) {
|
func (f *fakeRejectingNotificationPolicyService) GetPolicyTree(ctx context.Context, orgID int64) (definitions.Route, error) {
|
||||||
@ -355,6 +385,10 @@ func (f *fakeRejectingNotificationPolicyService) UpdatePolicyTree(ctx context.Co
|
|||||||
return fmt.Errorf("%w: invalid policy tree", provisioning.ErrValidation)
|
return fmt.Errorf("%w: invalid policy tree", provisioning.ErrValidation)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *fakeRejectingNotificationPolicyService) ResetPolicyTree(ctx context.Context, orgID int64) (definitions.Route, error) {
|
||||||
|
return definitions.Route{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func createInvalidContactPoint() definitions.EmbeddedContactPoint {
|
func createInvalidContactPoint() definitions.EmbeddedContactPoint {
|
||||||
settings, _ := simplejson.NewJson([]byte(`{}`))
|
settings, _ := simplejson.NewJson([]byte(`{}`))
|
||||||
return definitions.EmbeddedContactPoint{
|
return definitions.EmbeddedContactPoint{
|
||||||
|
@ -191,6 +191,7 @@ func (api *API) authorize(method, path string) web.Handler {
|
|||||||
eval = ac.EvalPermission(ac.ActionAlertingProvisioningRead) // organization scope
|
eval = ac.EvalPermission(ac.ActionAlertingProvisioningRead) // organization scope
|
||||||
|
|
||||||
case http.MethodPut + "/api/v1/provisioning/policies",
|
case http.MethodPut + "/api/v1/provisioning/policies",
|
||||||
|
http.MethodDelete + "/api/v1/provisioning/policies",
|
||||||
http.MethodPost + "/api/v1/provisioning/contact-points",
|
http.MethodPost + "/api/v1/provisioning/contact-points",
|
||||||
http.MethodPut + "/api/v1/provisioning/contact-points/{UID}",
|
http.MethodPut + "/api/v1/provisioning/contact-points/{UID}",
|
||||||
http.MethodDelete + "/api/v1/provisioning/contact-points/{UID}",
|
http.MethodDelete + "/api/v1/provisioning/contact-points/{UID}",
|
||||||
|
@ -27,6 +27,10 @@ func (f *ForkedProvisioningApi) forkRoutePutPolicyTree(ctx *models.ReqContext, r
|
|||||||
return f.svc.RoutePutPolicyTree(ctx, route)
|
return f.svc.RoutePutPolicyTree(ctx, route)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *ForkedProvisioningApi) forkRouteResetPolicyTree(ctx *models.ReqContext) response.Response {
|
||||||
|
return f.svc.RouteResetPolicyTree(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
func (f *ForkedProvisioningApi) forkRouteGetContactpoints(ctx *models.ReqContext) response.Response {
|
func (f *ForkedProvisioningApi) forkRouteGetContactpoints(ctx *models.ReqContext) response.Response {
|
||||||
return f.svc.RouteGetContactPoints(ctx)
|
return f.svc.RouteGetContactPoints(ctx)
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,7 @@ type ProvisioningApiForkingService interface {
|
|||||||
RoutePutMuteTiming(*models.ReqContext) response.Response
|
RoutePutMuteTiming(*models.ReqContext) response.Response
|
||||||
RoutePutPolicyTree(*models.ReqContext) response.Response
|
RoutePutPolicyTree(*models.ReqContext) response.Response
|
||||||
RoutePutTemplate(*models.ReqContext) response.Response
|
RoutePutTemplate(*models.ReqContext) response.Response
|
||||||
|
RouteResetPolicyTree(*models.ReqContext) response.Response
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *ForkedProvisioningApi) RouteDeleteAlertRule(ctx *models.ReqContext) response.Response {
|
func (f *ForkedProvisioningApi) RouteDeleteAlertRule(ctx *models.ReqContext) response.Response {
|
||||||
@ -156,6 +157,9 @@ func (f *ForkedProvisioningApi) RoutePutTemplate(ctx *models.ReqContext) respons
|
|||||||
}
|
}
|
||||||
return f.forkRoutePutTemplate(ctx, conf, nameParam)
|
return f.forkRoutePutTemplate(ctx, conf, nameParam)
|
||||||
}
|
}
|
||||||
|
func (f *ForkedProvisioningApi) RouteResetPolicyTree(ctx *models.ReqContext) response.Response {
|
||||||
|
return f.forkRouteResetPolicyTree(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
func (api *API) RegisterProvisioningApiEndpoints(srv ProvisioningApiForkingService, m *metrics.API) {
|
func (api *API) RegisterProvisioningApiEndpoints(srv ProvisioningApiForkingService, m *metrics.API) {
|
||||||
api.RouteRegister.Group("", func(group routing.RouteRegister) {
|
api.RouteRegister.Group("", func(group routing.RouteRegister) {
|
||||||
@ -369,5 +373,15 @@ func (api *API) RegisterProvisioningApiEndpoints(srv ProvisioningApiForkingServi
|
|||||||
m,
|
m,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
group.Delete(
|
||||||
|
toMacaronPath("/api/v1/provisioning/policies"),
|
||||||
|
api.authorize(http.MethodDelete, "/api/v1/provisioning/policies"),
|
||||||
|
metrics.Instrument(
|
||||||
|
http.MethodDelete,
|
||||||
|
"/api/v1/provisioning/policies",
|
||||||
|
srv.RouteResetPolicyTree,
|
||||||
|
m,
|
||||||
|
),
|
||||||
|
)
|
||||||
}, middleware.ReqSignedIn)
|
}, middleware.ReqSignedIn)
|
||||||
}
|
}
|
||||||
|
@ -2785,6 +2785,7 @@
|
|||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
"alertGroups": {
|
"alertGroups": {
|
||||||
|
"description": "AlertGroups alert groups",
|
||||||
"items": {
|
"items": {
|
||||||
"$ref": "#/definitions/alertGroup"
|
"$ref": "#/definitions/alertGroup"
|
||||||
},
|
},
|
||||||
@ -3113,6 +3114,7 @@
|
|||||||
"type": "array"
|
"type": "array"
|
||||||
},
|
},
|
||||||
"postableSilence": {
|
"postableSilence": {
|
||||||
|
"description": "PostableSilence postable silence",
|
||||||
"properties": {
|
"properties": {
|
||||||
"comment": {
|
"comment": {
|
||||||
"description": "comment",
|
"description": "comment",
|
||||||
@ -3150,7 +3152,6 @@
|
|||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
"receiver": {
|
"receiver": {
|
||||||
"description": "Receiver receiver",
|
|
||||||
"properties": {
|
"properties": {
|
||||||
"name": {
|
"name": {
|
||||||
"description": "name",
|
"description": "name",
|
||||||
@ -3718,6 +3719,24 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/api/v1/provisioning/policies": {
|
"/api/v1/provisioning/policies": {
|
||||||
|
"delete": {
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"operationId": "RouteResetPolicyTree",
|
||||||
|
"responses": {
|
||||||
|
"202": {
|
||||||
|
"description": "Ack",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/Ack"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"summary": "Clears the notification policy tree.",
|
||||||
|
"tags": [
|
||||||
|
"provisioning"
|
||||||
|
]
|
||||||
|
},
|
||||||
"get": {
|
"get": {
|
||||||
"operationId": "RouteGetPolicyTree",
|
"operationId": "RouteGetPolicyTree",
|
||||||
"responses": {
|
"responses": {
|
||||||
|
@ -19,6 +19,16 @@ package definitions
|
|||||||
// 202: Ack
|
// 202: Ack
|
||||||
// 400: ValidationError
|
// 400: ValidationError
|
||||||
|
|
||||||
|
// swagger:route DELETE /api/v1/provisioning/policies provisioning stable RouteResetPolicyTree
|
||||||
|
//
|
||||||
|
// Clears the notification policy tree.
|
||||||
|
//
|
||||||
|
// Consumes:
|
||||||
|
// - application/json
|
||||||
|
//
|
||||||
|
// Responses:
|
||||||
|
// 202: Ack
|
||||||
|
|
||||||
// swagger:parameters RoutePutPolicyTree
|
// swagger:parameters RoutePutPolicyTree
|
||||||
type Policytree struct {
|
type Policytree struct {
|
||||||
// The new notification routing tree to use
|
// The new notification routing tree to use
|
||||||
|
@ -3003,6 +3003,7 @@
|
|||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
"gettableSilences": {
|
"gettableSilences": {
|
||||||
|
"description": "GettableSilences gettable silences",
|
||||||
"items": {
|
"items": {
|
||||||
"$ref": "#/definitions/gettableSilence"
|
"$ref": "#/definitions/gettableSilence"
|
||||||
},
|
},
|
||||||
@ -5344,6 +5345,24 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/api/v1/provisioning/policies": {
|
"/api/v1/provisioning/policies": {
|
||||||
|
"delete": {
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"operationId": "RouteResetPolicyTree",
|
||||||
|
"responses": {
|
||||||
|
"202": {
|
||||||
|
"description": "Ack",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/Ack"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"summary": "Clears the notification policy tree.",
|
||||||
|
"tags": [
|
||||||
|
"provisioning"
|
||||||
|
]
|
||||||
|
},
|
||||||
"get": {
|
"get": {
|
||||||
"operationId": "RouteGetPolicyTree",
|
"operationId": "RouteGetPolicyTree",
|
||||||
"responses": {
|
"responses": {
|
||||||
|
@ -2169,6 +2169,25 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"delete": {
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"provisioning",
|
||||||
|
"stable"
|
||||||
|
],
|
||||||
|
"summary": "Clears the notification policy tree.",
|
||||||
|
"operationId": "RouteResetPolicyTree",
|
||||||
|
"responses": {
|
||||||
|
"202": {
|
||||||
|
"description": "Ack",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/Ack"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/api/v1/provisioning/templates": {
|
"/api/v1/provisioning/templates": {
|
||||||
@ -5366,6 +5385,7 @@
|
|||||||
"$ref": "#/definitions/gettableSilence"
|
"$ref": "#/definitions/gettableSilence"
|
||||||
},
|
},
|
||||||
"gettableSilences": {
|
"gettableSilences": {
|
||||||
|
"description": "GettableSilences gettable silences",
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
"$ref": "#/definitions/gettableSilence"
|
"$ref": "#/definitions/gettableSilence"
|
||||||
@ -5477,6 +5497,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"postableSilence": {
|
"postableSilence": {
|
||||||
|
"description": "PostableSilence postable silence",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
"comment",
|
"comment",
|
||||||
|
@ -158,7 +158,7 @@ func (ng *AlertNG) init() error {
|
|||||||
ng.schedule = scheduler
|
ng.schedule = scheduler
|
||||||
|
|
||||||
// Provisioning
|
// Provisioning
|
||||||
policyService := provisioning.NewNotificationPolicyService(store, store, store, ng.Log)
|
policyService := provisioning.NewNotificationPolicyService(store, store, store, ng.Cfg.UnifiedAlerting, ng.Log)
|
||||||
contactPointService := provisioning.NewContactPointService(store, ng.SecretsService, store, store, ng.Log)
|
contactPointService := provisioning.NewContactPointService(store, ng.SecretsService, store, store, ng.Log)
|
||||||
templateService := provisioning.NewTemplateService(store, store, store, ng.Log)
|
templateService := provisioning.NewTemplateService(store, store, store, ng.Log)
|
||||||
muteTimingService := provisioning.NewMuteTimingService(store, store, store, ng.Log)
|
muteTimingService := provisioning.NewMuteTimingService(store, store, store, ng.Log)
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/infra/log"
|
"github.com/grafana/grafana/pkg/infra/log"
|
||||||
"github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
|
"github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
|
||||||
"github.com/grafana/grafana/pkg/services/ngalert/models"
|
"github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||||
|
"github.com/grafana/grafana/pkg/setting"
|
||||||
)
|
)
|
||||||
|
|
||||||
type NotificationPolicyService struct {
|
type NotificationPolicyService struct {
|
||||||
@ -14,15 +15,17 @@ type NotificationPolicyService struct {
|
|||||||
provenanceStore ProvisioningStore
|
provenanceStore ProvisioningStore
|
||||||
xact TransactionManager
|
xact TransactionManager
|
||||||
log log.Logger
|
log log.Logger
|
||||||
|
settings setting.UnifiedAlertingSettings
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewNotificationPolicyService(am AMConfigStore, prov ProvisioningStore,
|
func NewNotificationPolicyService(am AMConfigStore, prov ProvisioningStore,
|
||||||
xact TransactionManager, log log.Logger) *NotificationPolicyService {
|
xact TransactionManager, settings setting.UnifiedAlertingSettings, log log.Logger) *NotificationPolicyService {
|
||||||
return &NotificationPolicyService{
|
return &NotificationPolicyService{
|
||||||
amStore: am,
|
amStore: am,
|
||||||
provenanceStore: prov,
|
provenanceStore: prov,
|
||||||
xact: xact,
|
xact: xact,
|
||||||
log: log,
|
log: log,
|
||||||
|
settings: settings,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,6 +119,49 @@ func (nps *NotificationPolicyService) UpdatePolicyTree(ctx context.Context, orgI
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (nps *NotificationPolicyService) ResetPolicyTree(ctx context.Context, orgID int64) (definitions.Route, error) {
|
||||||
|
defaultCfg, err := deserializeAlertmanagerConfig([]byte(nps.settings.DefaultConfiguration))
|
||||||
|
if err != nil {
|
||||||
|
nps.log.Error("failed to parse default alertmanager config: %w", err)
|
||||||
|
return definitions.Route{}, fmt.Errorf("failed to parse default alertmanager config: %w", err)
|
||||||
|
}
|
||||||
|
route := defaultCfg.AlertmanagerConfig.Route
|
||||||
|
|
||||||
|
revision, err := getLastConfiguration(ctx, orgID, nps.amStore)
|
||||||
|
if err != nil {
|
||||||
|
return definitions.Route{}, err
|
||||||
|
}
|
||||||
|
revision.cfg.AlertmanagerConfig.Config.Route = route
|
||||||
|
|
||||||
|
serialized, err := serializeAlertmanagerConfig(*revision.cfg)
|
||||||
|
if err != nil {
|
||||||
|
return definitions.Route{}, err
|
||||||
|
}
|
||||||
|
cmd := models.SaveAlertmanagerConfigurationCmd{
|
||||||
|
AlertmanagerConfiguration: string(serialized),
|
||||||
|
ConfigurationVersion: revision.version,
|
||||||
|
FetchedConfigurationHash: revision.concurrencyToken,
|
||||||
|
Default: false,
|
||||||
|
OrgID: orgID,
|
||||||
|
}
|
||||||
|
err = nps.xact.InTransaction(ctx, func(ctx context.Context) error {
|
||||||
|
err := nps.amStore.UpdateAlertmanagerConfiguration(ctx, &cmd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = nps.provenanceStore.DeleteProvenance(ctx, route, orgID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return definitions.Route{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return *route, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (nps *NotificationPolicyService) receiversToMap(records []*definitions.PostableApiReceiver) (map[string]struct{}, error) {
|
func (nps *NotificationPolicyService) receiversToMap(records []*definitions.PostableApiReceiver) (map[string]struct{}, error) {
|
||||||
receivers := map[string]struct{}{}
|
receivers := map[string]struct{}{}
|
||||||
for _, receiver := range records {
|
for _, receiver := range records {
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/infra/log"
|
"github.com/grafana/grafana/pkg/infra/log"
|
||||||
"github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
|
"github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
|
||||||
"github.com/grafana/grafana/pkg/services/ngalert/models"
|
"github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||||
|
"github.com/grafana/grafana/pkg/setting"
|
||||||
"github.com/prometheus/alertmanager/config"
|
"github.com/prometheus/alertmanager/config"
|
||||||
"github.com/prometheus/alertmanager/timeinterval"
|
"github.com/prometheus/alertmanager/timeinterval"
|
||||||
"github.com/prometheus/common/model"
|
"github.com/prometheus/common/model"
|
||||||
@ -213,6 +214,17 @@ func TestNotificationPolicyService(t *testing.T) {
|
|||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
require.ErrorIs(t, err, ErrValidation)
|
require.ErrorIs(t, err, ErrValidation)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("deleting route replaces with default", func(t *testing.T) {
|
||||||
|
sut := createNotificationPolicyServiceSut()
|
||||||
|
|
||||||
|
tree, err := sut.ResetPolicyTree(context.Background(), 1)
|
||||||
|
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, "grafana-default-email", tree.Receiver)
|
||||||
|
require.Nil(t, tree.Routes)
|
||||||
|
require.Nil(t, tree.GroupBy)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func createNotificationPolicyServiceSut() *NotificationPolicyService {
|
func createNotificationPolicyServiceSut() *NotificationPolicyService {
|
||||||
@ -221,6 +233,9 @@ func createNotificationPolicyServiceSut() *NotificationPolicyService {
|
|||||||
provenanceStore: NewFakeProvisioningStore(),
|
provenanceStore: NewFakeProvisioningStore(),
|
||||||
xact: newNopTransactionManager(),
|
xact: newNopTransactionManager(),
|
||||||
log: log.NewNopLogger(),
|
log: log.NewNopLogger(),
|
||||||
|
settings: setting.UnifiedAlertingSettings{
|
||||||
|
DefaultConfiguration: setting.GetAlertmanagerDefaultConfiguration(),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user