Alerting: Endpoints for provisioning mute timings (#49635) (#49735)

* Add validator for mute timing and make it provisionable

* Add tests to ensure prometheus validators are running and errors are propagated

* Internal API for manipulating mute timings

* Define and generate API layer

* Wire up generated code

* Implement API handlers

* Tests for golang layer

* Fix reference bug

* Fix linter and auth tests

* Resolve semantic errors and regenerate

* Remove pointless comment

* Extract out provisioning path param keys, simplify

* Expected number of paths

(cherry picked from commit 909ebcf979)

Co-authored-by: Alexander Weaver <weaver.alex.d@gmail.com>
This commit is contained in:
Grot (@grafanabot)
2022-05-26 16:06:52 -05:00
committed by GitHub
co-authored by Alexander Weaver
parent ccd1270f28
commit 7e4327d254
14 changed files with 1003 additions and 132 deletions
+55 -9
View File
@@ -16,6 +16,9 @@ import (
"github.com/grafana/grafana/pkg/web"
)
const namePathParam = ":name"
const idPathParam = ":ID"
type ProvisioningSrv struct {
log log.Logger
policies NotificationPolicyService
@@ -43,7 +46,10 @@ type NotificationPolicyService interface {
}
type MuteTimingService interface {
GetMuteTimings(ctx context.Context, orgID int64) ([]apimodels.MuteTiming, error)
GetMuteTimings(ctx context.Context, orgID int64) ([]apimodels.MuteTimeInterval, error)
CreateMuteTiming(ctx context.Context, mt apimodels.MuteTimeInterval, orgID int64) (*apimodels.MuteTimeInterval, error)
UpdateMuteTiming(ctx context.Context, mt apimodels.MuteTimeInterval, orgID int64) (*apimodels.MuteTimeInterval, error)
DeleteMuteTiming(ctx context.Context, name string, orgID int64) error
}
func (srv *ProvisioningSrv) RouteGetPolicyTree(c *models.ReqContext) response.Response {
@@ -91,7 +97,7 @@ func (srv *ProvisioningSrv) RoutePostContactPoint(c *models.ReqContext, cp apimo
}
func (srv *ProvisioningSrv) RoutePutContactPoint(c *models.ReqContext, cp apimodels.EmbeddedContactPoint) response.Response {
id := web.Params(c.Req)[":ID"]
id := pathParam(c, idPathParam)
cp.UID = id
err := srv.contactPointService.UpdateContactPoint(c.Req.Context(), c.OrgId, cp, alerting_models.ProvenanceAPI)
if err != nil {
@@ -101,7 +107,7 @@ func (srv *ProvisioningSrv) RoutePutContactPoint(c *models.ReqContext, cp apimod
}
func (srv *ProvisioningSrv) RouteDeleteContactPoint(c *models.ReqContext) response.Response {
cpID := web.Params(c.Req)[":ID"]
cpID := pathParam(c, idPathParam)
err := srv.contactPointService.DeleteContactPoint(c.Req.Context(), c.OrgId, cpID)
if err != nil {
return ErrResp(http.StatusInternalServerError, err, "")
@@ -122,19 +128,19 @@ func (srv *ProvisioningSrv) RouteGetTemplates(c *models.ReqContext) response.Res
}
func (srv *ProvisioningSrv) RouteGetTemplate(c *models.ReqContext) response.Response {
id := web.Params(c.Req)[":name"]
name := pathParam(c, namePathParam)
templates, err := srv.templates.GetTemplates(c.Req.Context(), c.OrgId)
if err != nil {
return ErrResp(http.StatusInternalServerError, err, "")
}
if tmpl, ok := templates[id]; ok {
return response.JSON(http.StatusOK, apimodels.MessageTemplate{Name: id, Template: tmpl})
if tmpl, ok := templates[name]; ok {
return response.JSON(http.StatusOK, apimodels.MessageTemplate{Name: name, Template: tmpl})
}
return response.Empty(http.StatusNotFound)
}
func (srv *ProvisioningSrv) RoutePutTemplate(c *models.ReqContext, body apimodels.MessageTemplateContent) response.Response {
name := web.Params(c.Req)[":name"]
name := pathParam(c, namePathParam)
tmpl := apimodels.MessageTemplate{
Name: name,
Template: body.Template,
@@ -151,7 +157,7 @@ func (srv *ProvisioningSrv) RoutePutTemplate(c *models.ReqContext, body apimodel
}
func (srv *ProvisioningSrv) RouteDeleteTemplate(c *models.ReqContext) response.Response {
name := web.Params(c.Req)[":name"]
name := pathParam(c, namePathParam)
err := srv.templates.DeleteTemplate(c.Req.Context(), c.OrgId, name)
if err != nil {
return ErrResp(http.StatusInternalServerError, err, "")
@@ -160,7 +166,7 @@ func (srv *ProvisioningSrv) RouteDeleteTemplate(c *models.ReqContext) response.R
}
func (srv *ProvisioningSrv) RouteGetMuteTiming(c *models.ReqContext) response.Response {
name := web.Params(c.Req)[":name"]
name := pathParam(c, namePathParam)
timings, err := srv.muteTimings.GetMuteTimings(c.Req.Context(), c.OrgId)
if err != nil {
return ErrResp(http.StatusInternalServerError, err, "")
@@ -180,3 +186,43 @@ func (srv *ProvisioningSrv) RouteGetMuteTimings(c *models.ReqContext) response.R
}
return response.JSON(http.StatusOK, timings)
}
func (srv *ProvisioningSrv) RoutePostMuteTiming(c *models.ReqContext, mt apimodels.MuteTimeInterval) response.Response {
created, err := srv.muteTimings.CreateMuteTiming(c.Req.Context(), mt, c.OrgId)
if err != nil {
if errors.Is(err, provisioning.ErrValidation) {
return ErrResp(http.StatusBadRequest, err, "")
}
return ErrResp(http.StatusInternalServerError, err, "")
}
return response.JSON(http.StatusCreated, created)
}
func (srv *ProvisioningSrv) RoutePutMuteTiming(c *models.ReqContext, mt apimodels.MuteTimeInterval) response.Response {
name := pathParam(c, namePathParam)
mt.Name = name
updated, err := srv.muteTimings.UpdateMuteTiming(c.Req.Context(), mt, c.OrgId)
if err != nil {
if errors.Is(err, provisioning.ErrValidation) {
return ErrResp(http.StatusBadRequest, err, "")
}
return ErrResp(http.StatusInternalServerError, err, "")
}
if updated == nil {
return response.Empty(http.StatusNotFound)
}
return response.JSON(http.StatusAccepted, updated)
}
func (srv *ProvisioningSrv) RouteDeleteMuteTiming(c *models.ReqContext) response.Response {
name := pathParam(c, namePathParam)
err := srv.muteTimings.DeleteMuteTiming(c.Req.Context(), name, c.OrgId)
if err != nil {
return ErrResp(http.StatusInternalServerError, err, "")
}
return response.JSON(http.StatusNoContent, nil)
}
func pathParam(c *models.ReqContext, param string) string {
return web.Params(c.Req)[param]
}