mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Alerting: Provisioning API - Alert rules (#47930)
This commit is contained in:
parent
5dbea9996b
commit
81d360529b
@ -81,6 +81,7 @@ type API struct {
|
||||
ContactPointService *provisioning.ContactPointService
|
||||
Templates *provisioning.TemplateService
|
||||
MuteTimings *provisioning.MuteTimingService
|
||||
AlertRules *provisioning.AlertRuleService
|
||||
}
|
||||
|
||||
// RegisterAPIEndpoints registers API handlers
|
||||
@ -142,6 +143,7 @@ func (api *API) RegisterAPIEndpoints(m *metrics.API) {
|
||||
contactPointService: api.ContactPointService,
|
||||
templates: api.Templates,
|
||||
muteTimings: api.MuteTimings,
|
||||
alertRules: api.AlertRules,
|
||||
}), m)
|
||||
}
|
||||
}
|
||||
|
@ -16,8 +16,13 @@ import (
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
)
|
||||
|
||||
const namePathParam = ":name"
|
||||
const idPathParam = ":ID"
|
||||
const (
|
||||
namePathParam = ":name"
|
||||
idPathParam = ":ID"
|
||||
uidPathParam = ":UID"
|
||||
groupPathParam = ":Group"
|
||||
folderUIDPathParam = ":FolderUID"
|
||||
)
|
||||
|
||||
type ProvisioningSrv struct {
|
||||
log log.Logger
|
||||
@ -25,6 +30,7 @@ type ProvisioningSrv struct {
|
||||
contactPointService ContactPointService
|
||||
templates TemplateService
|
||||
muteTimings MuteTimingService
|
||||
alertRules AlertRuleService
|
||||
}
|
||||
|
||||
type ContactPointService interface {
|
||||
@ -52,6 +58,14 @@ type MuteTimingService interface {
|
||||
DeleteMuteTiming(ctx context.Context, name string, orgID int64) error
|
||||
}
|
||||
|
||||
type AlertRuleService interface {
|
||||
GetAlertRule(ctx context.Context, orgID int64, ruleUID string) (alerting_models.AlertRule, alerting_models.Provenance, error)
|
||||
CreateAlertRule(ctx context.Context, rule alerting_models.AlertRule, provenance alerting_models.Provenance) (alerting_models.AlertRule, error)
|
||||
UpdateAlertRule(ctx context.Context, rule alerting_models.AlertRule, provenance alerting_models.Provenance) (alerting_models.AlertRule, error)
|
||||
DeleteAlertRule(ctx context.Context, orgID int64, ruleUID string, provenance alerting_models.Provenance) error
|
||||
UpdateAlertGroup(ctx context.Context, orgID int64, folderUID, rulegroup string, interval int64) error
|
||||
}
|
||||
|
||||
func (srv *ProvisioningSrv) RouteGetPolicyTree(c *models.ReqContext) response.Response {
|
||||
policies, err := srv.policies.GetPolicyTree(c.Req.Context(), c.OrgId)
|
||||
if errors.Is(err, store.ErrNoAlertmanagerConfiguration) {
|
||||
@ -223,6 +237,54 @@ func (srv *ProvisioningSrv) RouteDeleteMuteTiming(c *models.ReqContext) response
|
||||
return response.JSON(http.StatusNoContent, nil)
|
||||
}
|
||||
|
||||
func (srv *ProvisioningSrv) RouteRouteGetAlertRule(c *models.ReqContext) response.Response {
|
||||
uid := pathParam(c, uidPathParam)
|
||||
rule, provenace, err := srv.alertRules.GetAlertRule(c.Req.Context(), c.OrgId, uid)
|
||||
if err != nil {
|
||||
return ErrResp(http.StatusInternalServerError, err, "")
|
||||
}
|
||||
return response.JSON(http.StatusOK, apimodels.NewAlertRule(rule, provenace))
|
||||
}
|
||||
|
||||
func (srv *ProvisioningSrv) RoutePostAlertRule(c *models.ReqContext, ar apimodels.AlertRule) response.Response {
|
||||
createdAlertRule, err := srv.alertRules.CreateAlertRule(c.Req.Context(), ar.UpstreamModel(), alerting_models.ProvenanceAPI)
|
||||
if err != nil {
|
||||
return ErrResp(http.StatusInternalServerError, err, "")
|
||||
}
|
||||
ar.ID = createdAlertRule.ID
|
||||
ar.UID = createdAlertRule.UID
|
||||
ar.Updated = createdAlertRule.Updated
|
||||
return response.JSON(http.StatusCreated, ar)
|
||||
}
|
||||
|
||||
func (srv *ProvisioningSrv) RoutePutAlertRule(c *models.ReqContext, ar apimodels.AlertRule) response.Response {
|
||||
updatedAlertRule, err := srv.alertRules.UpdateAlertRule(c.Req.Context(), ar.UpstreamModel(), alerting_models.ProvenanceAPI)
|
||||
if err != nil {
|
||||
return ErrResp(http.StatusInternalServerError, err, "")
|
||||
}
|
||||
ar.Updated = updatedAlertRule.Updated
|
||||
return response.JSON(http.StatusOK, ar)
|
||||
}
|
||||
|
||||
func (srv *ProvisioningSrv) RouteDeleteAlertRule(c *models.ReqContext) response.Response {
|
||||
uid := pathParam(c, uidPathParam)
|
||||
err := srv.alertRules.DeleteAlertRule(c.Req.Context(), c.OrgId, uid, alerting_models.ProvenanceAPI)
|
||||
if err != nil {
|
||||
return ErrResp(http.StatusInternalServerError, err, "")
|
||||
}
|
||||
return response.JSON(http.StatusNoContent, "")
|
||||
}
|
||||
|
||||
func (srv *ProvisioningSrv) RoutePutAlertRuleGroup(c *models.ReqContext, ag apimodels.AlertRuleGroup) response.Response {
|
||||
rulegroup := pathParam(c, groupPathParam)
|
||||
folderUID := pathParam(c, folderUIDPathParam)
|
||||
err := srv.alertRules.UpdateAlertGroup(c.Req.Context(), c.OrgId, folderUID, rulegroup, ag.Interval)
|
||||
if err != nil {
|
||||
return ErrResp(http.StatusInternalServerError, err, "")
|
||||
}
|
||||
return response.JSON(http.StatusOK, ag)
|
||||
}
|
||||
|
||||
func pathParam(c *models.ReqContext, param string) string {
|
||||
return web.Params(c.Req)[param]
|
||||
}
|
||||
|
@ -422,7 +422,7 @@ func (srv RulerSrv) updateAlertRulesInGroup(c *models.ReqContext, groupKey ngmod
|
||||
for _, rule := range finalChanges.New {
|
||||
inserts = append(inserts, *rule)
|
||||
}
|
||||
err = srv.store.InsertAlertRules(tranCtx, inserts)
|
||||
_, err = srv.store.InsertAlertRules(tranCtx, inserts)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to add rules: %w", err)
|
||||
}
|
||||
|
@ -184,7 +184,8 @@ func (api *API) authorize(method, path string) web.Handler {
|
||||
http.MethodGet + "/api/provisioning/templates",
|
||||
http.MethodGet + "/api/provisioning/templates/{name}",
|
||||
http.MethodGet + "/api/provisioning/mute-timings",
|
||||
http.MethodGet + "/api/provisioning/mute-timings/{name}":
|
||||
http.MethodGet + "/api/provisioning/mute-timings/{name}",
|
||||
http.MethodGet + "/api/provisioning/alert-rules/{UID}":
|
||||
return middleware.ReqSignedIn
|
||||
|
||||
case http.MethodPut + "/api/provisioning/policies",
|
||||
@ -195,7 +196,11 @@ func (api *API) authorize(method, path string) web.Handler {
|
||||
http.MethodDelete + "/api/provisioning/templates/{name}",
|
||||
http.MethodPost + "/api/provisioning/mute-timings",
|
||||
http.MethodPut + "/api/provisioning/mute-timings/{name}",
|
||||
http.MethodDelete + "/api/provisioning/mute-timings/{name}":
|
||||
http.MethodDelete + "/api/provisioning/mute-timings/{name}",
|
||||
http.MethodPost + "/api/provisioning/alert-rules",
|
||||
http.MethodPut + "/api/provisioning/alert-rules/{UID}",
|
||||
http.MethodDelete + "/api/provisioning/alert-rules/{UID}",
|
||||
http.MethodPut + "/api/provisioning/folder/{FolderUID}/rule-groups/{Group}":
|
||||
return middleware.ReqEditorRole
|
||||
}
|
||||
|
||||
|
@ -48,7 +48,7 @@ func TestAuthorize(t *testing.T) {
|
||||
}
|
||||
paths[p] = methods
|
||||
}
|
||||
require.Len(t, paths, 36)
|
||||
require.Len(t, paths, 39)
|
||||
|
||||
ac := acmock.New()
|
||||
api := &API{AccessControl: ac}
|
||||
|
@ -78,3 +78,23 @@ func (f *ForkedProvisioningApi) forkRoutePutMuteTiming(ctx *models.ReqContext, m
|
||||
func (f *ForkedProvisioningApi) forkRouteDeleteMuteTiming(ctx *models.ReqContext) response.Response {
|
||||
return f.svc.RouteDeleteMuteTiming(ctx)
|
||||
}
|
||||
|
||||
func (f *ForkedProvisioningApi) forkRouteGetAlertRule(ctx *models.ReqContext) response.Response {
|
||||
return f.svc.RouteRouteGetAlertRule(ctx)
|
||||
}
|
||||
|
||||
func (f *ForkedProvisioningApi) forkRoutePostAlertRule(ctx *models.ReqContext, ar apimodels.AlertRule) response.Response {
|
||||
return f.svc.RoutePostAlertRule(ctx, ar)
|
||||
}
|
||||
|
||||
func (f *ForkedProvisioningApi) forkRoutePutAlertRule(ctx *models.ReqContext, ar apimodels.AlertRule) response.Response {
|
||||
return f.svc.RoutePutAlertRule(ctx, ar)
|
||||
}
|
||||
|
||||
func (f *ForkedProvisioningApi) forkRouteDeleteAlertRule(ctx *models.ReqContext) response.Response {
|
||||
return f.svc.RouteDeleteAlertRule(ctx)
|
||||
}
|
||||
|
||||
func (f *ForkedProvisioningApi) forkRoutePutAlertRuleGroup(ctx *models.ReqContext, ag apimodels.AlertRuleGroup) response.Response {
|
||||
return f.svc.RoutePutAlertRuleGroup(ctx, ag)
|
||||
}
|
||||
|
@ -4,7 +4,6 @@
|
||||
*
|
||||
*Do not manually edit these files, please find ngalert/api/swagger-codegen/ for commands on how to generate them.
|
||||
*/
|
||||
|
||||
package api
|
||||
|
||||
import (
|
||||
@ -53,7 +52,6 @@ func (f *ForkedAlertmanagerApi) RouteCreateGrafanaSilence(ctx *models.ReqContext
|
||||
}
|
||||
return f.forkRouteCreateGrafanaSilence(ctx, conf)
|
||||
}
|
||||
|
||||
func (f *ForkedAlertmanagerApi) RouteCreateSilence(ctx *models.ReqContext) response.Response {
|
||||
conf := apimodels.PostableSilence{}
|
||||
if err := web.Bind(ctx.Req, &conf); err != nil {
|
||||
@ -61,71 +59,54 @@ func (f *ForkedAlertmanagerApi) RouteCreateSilence(ctx *models.ReqContext) respo
|
||||
}
|
||||
return f.forkRouteCreateSilence(ctx, conf)
|
||||
}
|
||||
|
||||
func (f *ForkedAlertmanagerApi) RouteDeleteAlertingConfig(ctx *models.ReqContext) response.Response {
|
||||
return f.forkRouteDeleteAlertingConfig(ctx)
|
||||
}
|
||||
|
||||
func (f *ForkedAlertmanagerApi) RouteDeleteGrafanaAlertingConfig(ctx *models.ReqContext) response.Response {
|
||||
return f.forkRouteDeleteGrafanaAlertingConfig(ctx)
|
||||
}
|
||||
|
||||
func (f *ForkedAlertmanagerApi) RouteDeleteGrafanaSilence(ctx *models.ReqContext) response.Response {
|
||||
return f.forkRouteDeleteGrafanaSilence(ctx)
|
||||
}
|
||||
|
||||
func (f *ForkedAlertmanagerApi) RouteDeleteSilence(ctx *models.ReqContext) response.Response {
|
||||
return f.forkRouteDeleteSilence(ctx)
|
||||
}
|
||||
|
||||
func (f *ForkedAlertmanagerApi) RouteGetAMAlertGroups(ctx *models.ReqContext) response.Response {
|
||||
return f.forkRouteGetAMAlertGroups(ctx)
|
||||
}
|
||||
|
||||
func (f *ForkedAlertmanagerApi) RouteGetAMAlerts(ctx *models.ReqContext) response.Response {
|
||||
return f.forkRouteGetAMAlerts(ctx)
|
||||
}
|
||||
|
||||
func (f *ForkedAlertmanagerApi) RouteGetAMStatus(ctx *models.ReqContext) response.Response {
|
||||
return f.forkRouteGetAMStatus(ctx)
|
||||
}
|
||||
|
||||
func (f *ForkedAlertmanagerApi) RouteGetAlertingConfig(ctx *models.ReqContext) response.Response {
|
||||
return f.forkRouteGetAlertingConfig(ctx)
|
||||
}
|
||||
|
||||
func (f *ForkedAlertmanagerApi) RouteGetGrafanaAMAlertGroups(ctx *models.ReqContext) response.Response {
|
||||
return f.forkRouteGetGrafanaAMAlertGroups(ctx)
|
||||
}
|
||||
|
||||
func (f *ForkedAlertmanagerApi) RouteGetGrafanaAMAlerts(ctx *models.ReqContext) response.Response {
|
||||
return f.forkRouteGetGrafanaAMAlerts(ctx)
|
||||
}
|
||||
|
||||
func (f *ForkedAlertmanagerApi) RouteGetGrafanaAMStatus(ctx *models.ReqContext) response.Response {
|
||||
return f.forkRouteGetGrafanaAMStatus(ctx)
|
||||
}
|
||||
|
||||
func (f *ForkedAlertmanagerApi) RouteGetGrafanaAlertingConfig(ctx *models.ReqContext) response.Response {
|
||||
return f.forkRouteGetGrafanaAlertingConfig(ctx)
|
||||
}
|
||||
|
||||
func (f *ForkedAlertmanagerApi) RouteGetGrafanaSilence(ctx *models.ReqContext) response.Response {
|
||||
return f.forkRouteGetGrafanaSilence(ctx)
|
||||
}
|
||||
|
||||
func (f *ForkedAlertmanagerApi) RouteGetGrafanaSilences(ctx *models.ReqContext) response.Response {
|
||||
return f.forkRouteGetGrafanaSilences(ctx)
|
||||
}
|
||||
|
||||
func (f *ForkedAlertmanagerApi) RouteGetSilence(ctx *models.ReqContext) response.Response {
|
||||
return f.forkRouteGetSilence(ctx)
|
||||
}
|
||||
|
||||
func (f *ForkedAlertmanagerApi) RouteGetSilences(ctx *models.ReqContext) response.Response {
|
||||
return f.forkRouteGetSilences(ctx)
|
||||
}
|
||||
|
||||
func (f *ForkedAlertmanagerApi) RoutePostAMAlerts(ctx *models.ReqContext) response.Response {
|
||||
conf := apimodels.PostableAlerts{}
|
||||
if err := web.Bind(ctx.Req, &conf); err != nil {
|
||||
@ -133,7 +114,6 @@ func (f *ForkedAlertmanagerApi) RoutePostAMAlerts(ctx *models.ReqContext) respon
|
||||
}
|
||||
return f.forkRoutePostAMAlerts(ctx, conf)
|
||||
}
|
||||
|
||||
func (f *ForkedAlertmanagerApi) RoutePostAlertingConfig(ctx *models.ReqContext) response.Response {
|
||||
conf := apimodels.PostableUserConfig{}
|
||||
if err := web.Bind(ctx.Req, &conf); err != nil {
|
||||
@ -141,7 +121,6 @@ func (f *ForkedAlertmanagerApi) RoutePostAlertingConfig(ctx *models.ReqContext)
|
||||
}
|
||||
return f.forkRoutePostAlertingConfig(ctx, conf)
|
||||
}
|
||||
|
||||
func (f *ForkedAlertmanagerApi) RoutePostGrafanaAMAlerts(ctx *models.ReqContext) response.Response {
|
||||
conf := apimodels.PostableAlerts{}
|
||||
if err := web.Bind(ctx.Req, &conf); err != nil {
|
||||
@ -149,7 +128,6 @@ func (f *ForkedAlertmanagerApi) RoutePostGrafanaAMAlerts(ctx *models.ReqContext)
|
||||
}
|
||||
return f.forkRoutePostGrafanaAMAlerts(ctx, conf)
|
||||
}
|
||||
|
||||
func (f *ForkedAlertmanagerApi) RoutePostGrafanaAlertingConfig(ctx *models.ReqContext) response.Response {
|
||||
conf := apimodels.PostableUserConfig{}
|
||||
if err := web.Bind(ctx.Req, &conf); err != nil {
|
||||
@ -157,7 +135,6 @@ func (f *ForkedAlertmanagerApi) RoutePostGrafanaAlertingConfig(ctx *models.ReqCo
|
||||
}
|
||||
return f.forkRoutePostGrafanaAlertingConfig(ctx, conf)
|
||||
}
|
||||
|
||||
func (f *ForkedAlertmanagerApi) RoutePostTestGrafanaReceivers(ctx *models.ReqContext) response.Response {
|
||||
conf := apimodels.TestReceiversConfigBodyParams{}
|
||||
if err := web.Bind(ctx.Req, &conf); err != nil {
|
||||
@ -165,7 +142,6 @@ func (f *ForkedAlertmanagerApi) RoutePostTestGrafanaReceivers(ctx *models.ReqCon
|
||||
}
|
||||
return f.forkRoutePostTestGrafanaReceivers(ctx, conf)
|
||||
}
|
||||
|
||||
func (f *ForkedAlertmanagerApi) RoutePostTestReceivers(ctx *models.ReqContext) response.Response {
|
||||
conf := apimodels.TestReceiversConfigBodyParams{}
|
||||
if err := web.Bind(ctx.Req, &conf); err != nil {
|
||||
|
@ -4,7 +4,6 @@
|
||||
*
|
||||
*Do not manually edit these files, please find ngalert/api/swagger-codegen/ for commands on how to generate them.
|
||||
*/
|
||||
|
||||
package api
|
||||
|
||||
import (
|
||||
@ -29,15 +28,12 @@ type ConfigurationApiForkingService interface {
|
||||
func (f *ForkedConfigurationApi) RouteDeleteNGalertConfig(ctx *models.ReqContext) response.Response {
|
||||
return f.forkRouteDeleteNGalertConfig(ctx)
|
||||
}
|
||||
|
||||
func (f *ForkedConfigurationApi) RouteGetAlertmanagers(ctx *models.ReqContext) response.Response {
|
||||
return f.forkRouteGetAlertmanagers(ctx)
|
||||
}
|
||||
|
||||
func (f *ForkedConfigurationApi) RouteGetNGalertConfig(ctx *models.ReqContext) response.Response {
|
||||
return f.forkRouteGetNGalertConfig(ctx)
|
||||
}
|
||||
|
||||
func (f *ForkedConfigurationApi) RoutePostNGalertConfig(ctx *models.ReqContext) response.Response {
|
||||
conf := apimodels.PostableNGalertConfig{}
|
||||
if err := web.Bind(ctx.Req, &conf); err != nil {
|
||||
|
@ -4,7 +4,6 @@
|
||||
*
|
||||
*Do not manually edit these files, please find ngalert/api/swagger-codegen/ for commands on how to generate them.
|
||||
*/
|
||||
|
||||
package api
|
||||
|
||||
import (
|
||||
@ -27,15 +26,12 @@ type PrometheusApiForkingService interface {
|
||||
func (f *ForkedPrometheusApi) RouteGetAlertStatuses(ctx *models.ReqContext) response.Response {
|
||||
return f.forkRouteGetAlertStatuses(ctx)
|
||||
}
|
||||
|
||||
func (f *ForkedPrometheusApi) RouteGetGrafanaAlertStatuses(ctx *models.ReqContext) response.Response {
|
||||
return f.forkRouteGetGrafanaAlertStatuses(ctx)
|
||||
}
|
||||
|
||||
func (f *ForkedPrometheusApi) RouteGetGrafanaRuleStatuses(ctx *models.ReqContext) response.Response {
|
||||
return f.forkRouteGetGrafanaRuleStatuses(ctx)
|
||||
}
|
||||
|
||||
func (f *ForkedPrometheusApi) RouteGetRuleStatuses(ctx *models.ReqContext) response.Response {
|
||||
return f.forkRouteGetRuleStatuses(ctx)
|
||||
}
|
||||
|
@ -4,7 +4,6 @@
|
||||
*
|
||||
*Do not manually edit these files, please find ngalert/api/swagger-codegen/ for commands on how to generate them.
|
||||
*/
|
||||
|
||||
package api
|
||||
|
||||
import (
|
||||
@ -20,59 +19,68 @@ import (
|
||||
)
|
||||
|
||||
type ProvisioningApiForkingService interface {
|
||||
RouteDeleteAlertRule(*models.ReqContext) response.Response
|
||||
RouteDeleteContactpoints(*models.ReqContext) response.Response
|
||||
RouteDeleteMuteTiming(*models.ReqContext) response.Response
|
||||
RouteDeleteTemplate(*models.ReqContext) response.Response
|
||||
RouteGetAlertRule(*models.ReqContext) response.Response
|
||||
RouteGetContactpoints(*models.ReqContext) response.Response
|
||||
RouteGetMuteTiming(*models.ReqContext) response.Response
|
||||
RouteGetMuteTimings(*models.ReqContext) response.Response
|
||||
RouteGetPolicyTree(*models.ReqContext) response.Response
|
||||
RouteGetTemplate(*models.ReqContext) response.Response
|
||||
RouteGetTemplates(*models.ReqContext) response.Response
|
||||
RoutePostAlertRule(*models.ReqContext) response.Response
|
||||
RoutePostContactpoints(*models.ReqContext) response.Response
|
||||
RoutePostMuteTiming(*models.ReqContext) response.Response
|
||||
RoutePutAlertRule(*models.ReqContext) response.Response
|
||||
RoutePutAlertRuleGroup(*models.ReqContext) response.Response
|
||||
RoutePutContactpoint(*models.ReqContext) response.Response
|
||||
RoutePutMuteTiming(*models.ReqContext) response.Response
|
||||
RoutePutPolicyTree(*models.ReqContext) response.Response
|
||||
RoutePutTemplate(*models.ReqContext) response.Response
|
||||
}
|
||||
|
||||
func (f *ForkedProvisioningApi) RouteDeleteAlertRule(ctx *models.ReqContext) response.Response {
|
||||
return f.forkRouteDeleteAlertRule(ctx)
|
||||
}
|
||||
func (f *ForkedProvisioningApi) RouteDeleteContactpoints(ctx *models.ReqContext) response.Response {
|
||||
return f.forkRouteDeleteContactpoints(ctx)
|
||||
}
|
||||
|
||||
func (f *ForkedProvisioningApi) RouteDeleteMuteTiming(ctx *models.ReqContext) response.Response {
|
||||
return f.forkRouteDeleteMuteTiming(ctx)
|
||||
}
|
||||
|
||||
func (f *ForkedProvisioningApi) RouteDeleteTemplate(ctx *models.ReqContext) response.Response {
|
||||
return f.forkRouteDeleteTemplate(ctx)
|
||||
}
|
||||
|
||||
func (f *ForkedProvisioningApi) RouteGetAlertRule(ctx *models.ReqContext) response.Response {
|
||||
return f.forkRouteGetAlertRule(ctx)
|
||||
}
|
||||
func (f *ForkedProvisioningApi) RouteGetContactpoints(ctx *models.ReqContext) response.Response {
|
||||
return f.forkRouteGetContactpoints(ctx)
|
||||
}
|
||||
|
||||
func (f *ForkedProvisioningApi) RouteGetMuteTiming(ctx *models.ReqContext) response.Response {
|
||||
return f.forkRouteGetMuteTiming(ctx)
|
||||
}
|
||||
|
||||
func (f *ForkedProvisioningApi) RouteGetMuteTimings(ctx *models.ReqContext) response.Response {
|
||||
return f.forkRouteGetMuteTimings(ctx)
|
||||
}
|
||||
|
||||
func (f *ForkedProvisioningApi) RouteGetPolicyTree(ctx *models.ReqContext) response.Response {
|
||||
return f.forkRouteGetPolicyTree(ctx)
|
||||
}
|
||||
|
||||
func (f *ForkedProvisioningApi) RouteGetTemplate(ctx *models.ReqContext) response.Response {
|
||||
return f.forkRouteGetTemplate(ctx)
|
||||
}
|
||||
|
||||
func (f *ForkedProvisioningApi) RouteGetTemplates(ctx *models.ReqContext) response.Response {
|
||||
return f.forkRouteGetTemplates(ctx)
|
||||
}
|
||||
|
||||
func (f *ForkedProvisioningApi) RoutePostAlertRule(ctx *models.ReqContext) response.Response {
|
||||
conf := apimodels.AlertRule{}
|
||||
if err := web.Bind(ctx.Req, &conf); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
return f.forkRoutePostAlertRule(ctx, conf)
|
||||
}
|
||||
func (f *ForkedProvisioningApi) RoutePostContactpoints(ctx *models.ReqContext) response.Response {
|
||||
conf := apimodels.EmbeddedContactPoint{}
|
||||
if err := web.Bind(ctx.Req, &conf); err != nil {
|
||||
@ -80,7 +88,6 @@ func (f *ForkedProvisioningApi) RoutePostContactpoints(ctx *models.ReqContext) r
|
||||
}
|
||||
return f.forkRoutePostContactpoints(ctx, conf)
|
||||
}
|
||||
|
||||
func (f *ForkedProvisioningApi) RoutePostMuteTiming(ctx *models.ReqContext) response.Response {
|
||||
conf := apimodels.MuteTimeInterval{}
|
||||
if err := web.Bind(ctx.Req, &conf); err != nil {
|
||||
@ -88,7 +95,20 @@ func (f *ForkedProvisioningApi) RoutePostMuteTiming(ctx *models.ReqContext) resp
|
||||
}
|
||||
return f.forkRoutePostMuteTiming(ctx, conf)
|
||||
}
|
||||
|
||||
func (f *ForkedProvisioningApi) RoutePutAlertRule(ctx *models.ReqContext) response.Response {
|
||||
conf := apimodels.AlertRule{}
|
||||
if err := web.Bind(ctx.Req, &conf); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
return f.forkRoutePutAlertRule(ctx, conf)
|
||||
}
|
||||
func (f *ForkedProvisioningApi) RoutePutAlertRuleGroup(ctx *models.ReqContext) response.Response {
|
||||
conf := apimodels.AlertRuleGroup{}
|
||||
if err := web.Bind(ctx.Req, &conf); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
return f.forkRoutePutAlertRuleGroup(ctx, conf)
|
||||
}
|
||||
func (f *ForkedProvisioningApi) RoutePutContactpoint(ctx *models.ReqContext) response.Response {
|
||||
conf := apimodels.EmbeddedContactPoint{}
|
||||
if err := web.Bind(ctx.Req, &conf); err != nil {
|
||||
@ -96,7 +116,6 @@ func (f *ForkedProvisioningApi) RoutePutContactpoint(ctx *models.ReqContext) res
|
||||
}
|
||||
return f.forkRoutePutContactpoint(ctx, conf)
|
||||
}
|
||||
|
||||
func (f *ForkedProvisioningApi) RoutePutMuteTiming(ctx *models.ReqContext) response.Response {
|
||||
conf := apimodels.MuteTimeInterval{}
|
||||
if err := web.Bind(ctx.Req, &conf); err != nil {
|
||||
@ -104,7 +123,6 @@ func (f *ForkedProvisioningApi) RoutePutMuteTiming(ctx *models.ReqContext) respo
|
||||
}
|
||||
return f.forkRoutePutMuteTiming(ctx, conf)
|
||||
}
|
||||
|
||||
func (f *ForkedProvisioningApi) RoutePutPolicyTree(ctx *models.ReqContext) response.Response {
|
||||
conf := apimodels.Route{}
|
||||
if err := web.Bind(ctx.Req, &conf); err != nil {
|
||||
@ -112,7 +130,6 @@ func (f *ForkedProvisioningApi) RoutePutPolicyTree(ctx *models.ReqContext) respo
|
||||
}
|
||||
return f.forkRoutePutPolicyTree(ctx, conf)
|
||||
}
|
||||
|
||||
func (f *ForkedProvisioningApi) RoutePutTemplate(ctx *models.ReqContext) response.Response {
|
||||
conf := apimodels.MessageTemplateContent{}
|
||||
if err := web.Bind(ctx.Req, &conf); err != nil {
|
||||
@ -123,6 +140,16 @@ func (f *ForkedProvisioningApi) RoutePutTemplate(ctx *models.ReqContext) respons
|
||||
|
||||
func (api *API) RegisterProvisioningApiEndpoints(srv ProvisioningApiForkingService, m *metrics.API) {
|
||||
api.RouteRegister.Group("", func(group routing.RouteRegister) {
|
||||
group.Delete(
|
||||
toMacaronPath("/api/provisioning/alert-rules/{UID}"),
|
||||
api.authorize(http.MethodDelete, "/api/provisioning/alert-rules/{UID}"),
|
||||
metrics.Instrument(
|
||||
http.MethodDelete,
|
||||
"/api/provisioning/alert-rules/{UID}",
|
||||
srv.RouteDeleteAlertRule,
|
||||
m,
|
||||
),
|
||||
)
|
||||
group.Delete(
|
||||
toMacaronPath("/api/provisioning/contact-points/{ID}"),
|
||||
api.authorize(http.MethodDelete, "/api/provisioning/contact-points/{ID}"),
|
||||
@ -153,6 +180,16 @@ func (api *API) RegisterProvisioningApiEndpoints(srv ProvisioningApiForkingServi
|
||||
m,
|
||||
),
|
||||
)
|
||||
group.Get(
|
||||
toMacaronPath("/api/provisioning/alert-rules/{UID}"),
|
||||
api.authorize(http.MethodGet, "/api/provisioning/alert-rules/{UID}"),
|
||||
metrics.Instrument(
|
||||
http.MethodGet,
|
||||
"/api/provisioning/alert-rules/{UID}",
|
||||
srv.RouteGetAlertRule,
|
||||
m,
|
||||
),
|
||||
)
|
||||
group.Get(
|
||||
toMacaronPath("/api/provisioning/contact-points"),
|
||||
api.authorize(http.MethodGet, "/api/provisioning/contact-points"),
|
||||
@ -213,6 +250,16 @@ func (api *API) RegisterProvisioningApiEndpoints(srv ProvisioningApiForkingServi
|
||||
m,
|
||||
),
|
||||
)
|
||||
group.Post(
|
||||
toMacaronPath("/api/provisioning/alert-rules"),
|
||||
api.authorize(http.MethodPost, "/api/provisioning/alert-rules"),
|
||||
metrics.Instrument(
|
||||
http.MethodPost,
|
||||
"/api/provisioning/alert-rules",
|
||||
srv.RoutePostAlertRule,
|
||||
m,
|
||||
),
|
||||
)
|
||||
group.Post(
|
||||
toMacaronPath("/api/provisioning/contact-points"),
|
||||
api.authorize(http.MethodPost, "/api/provisioning/contact-points"),
|
||||
@ -233,6 +280,26 @@ func (api *API) RegisterProvisioningApiEndpoints(srv ProvisioningApiForkingServi
|
||||
m,
|
||||
),
|
||||
)
|
||||
group.Put(
|
||||
toMacaronPath("/api/provisioning/alert-rules/{UID}"),
|
||||
api.authorize(http.MethodPut, "/api/provisioning/alert-rules/{UID}"),
|
||||
metrics.Instrument(
|
||||
http.MethodPut,
|
||||
"/api/provisioning/alert-rules/{UID}",
|
||||
srv.RoutePutAlertRule,
|
||||
m,
|
||||
),
|
||||
)
|
||||
group.Put(
|
||||
toMacaronPath("/api/provisioning/folder/{FolderUID}/rule-groups/{Group}"),
|
||||
api.authorize(http.MethodPut, "/api/provisioning/folder/{FolderUID}/rule-groups/{Group}"),
|
||||
metrics.Instrument(
|
||||
http.MethodPut,
|
||||
"/api/provisioning/folder/{FolderUID}/rule-groups/{Group}",
|
||||
srv.RoutePutAlertRuleGroup,
|
||||
m,
|
||||
),
|
||||
)
|
||||
group.Put(
|
||||
toMacaronPath("/api/provisioning/contact-points/{ID}"),
|
||||
api.authorize(http.MethodPut, "/api/provisioning/contact-points/{ID}"),
|
||||
|
@ -4,7 +4,6 @@
|
||||
*
|
||||
*Do not manually edit these files, please find ngalert/api/swagger-codegen/ for commands on how to generate them.
|
||||
*/
|
||||
|
||||
package api
|
||||
|
||||
import (
|
||||
@ -37,43 +36,33 @@ type RulerApiForkingService interface {
|
||||
func (f *ForkedRulerApi) RouteDeleteGrafanaRuleGroupConfig(ctx *models.ReqContext) response.Response {
|
||||
return f.forkRouteDeleteGrafanaRuleGroupConfig(ctx)
|
||||
}
|
||||
|
||||
func (f *ForkedRulerApi) RouteDeleteNamespaceGrafanaRulesConfig(ctx *models.ReqContext) response.Response {
|
||||
return f.forkRouteDeleteNamespaceGrafanaRulesConfig(ctx)
|
||||
}
|
||||
|
||||
func (f *ForkedRulerApi) RouteDeleteNamespaceRulesConfig(ctx *models.ReqContext) response.Response {
|
||||
return f.forkRouteDeleteNamespaceRulesConfig(ctx)
|
||||
}
|
||||
|
||||
func (f *ForkedRulerApi) RouteDeleteRuleGroupConfig(ctx *models.ReqContext) response.Response {
|
||||
return f.forkRouteDeleteRuleGroupConfig(ctx)
|
||||
}
|
||||
|
||||
func (f *ForkedRulerApi) RouteGetGrafanaRuleGroupConfig(ctx *models.ReqContext) response.Response {
|
||||
return f.forkRouteGetGrafanaRuleGroupConfig(ctx)
|
||||
}
|
||||
|
||||
func (f *ForkedRulerApi) RouteGetGrafanaRulesConfig(ctx *models.ReqContext) response.Response {
|
||||
return f.forkRouteGetGrafanaRulesConfig(ctx)
|
||||
}
|
||||
|
||||
func (f *ForkedRulerApi) RouteGetNamespaceGrafanaRulesConfig(ctx *models.ReqContext) response.Response {
|
||||
return f.forkRouteGetNamespaceGrafanaRulesConfig(ctx)
|
||||
}
|
||||
|
||||
func (f *ForkedRulerApi) RouteGetNamespaceRulesConfig(ctx *models.ReqContext) response.Response {
|
||||
return f.forkRouteGetNamespaceRulesConfig(ctx)
|
||||
}
|
||||
|
||||
func (f *ForkedRulerApi) RouteGetRulegGroupConfig(ctx *models.ReqContext) response.Response {
|
||||
return f.forkRouteGetRulegGroupConfig(ctx)
|
||||
}
|
||||
|
||||
func (f *ForkedRulerApi) RouteGetRulesConfig(ctx *models.ReqContext) response.Response {
|
||||
return f.forkRouteGetRulesConfig(ctx)
|
||||
}
|
||||
|
||||
func (f *ForkedRulerApi) RoutePostNameGrafanaRulesConfig(ctx *models.ReqContext) response.Response {
|
||||
conf := apimodels.PostableRuleGroupConfig{}
|
||||
if err := web.Bind(ctx.Req, &conf); err != nil {
|
||||
@ -81,7 +70,6 @@ func (f *ForkedRulerApi) RoutePostNameGrafanaRulesConfig(ctx *models.ReqContext)
|
||||
}
|
||||
return f.forkRoutePostNameGrafanaRulesConfig(ctx, conf)
|
||||
}
|
||||
|
||||
func (f *ForkedRulerApi) RoutePostNameRulesConfig(ctx *models.ReqContext) response.Response {
|
||||
conf := apimodels.PostableRuleGroupConfig{}
|
||||
if err := web.Bind(ctx.Req, &conf); err != nil {
|
||||
|
@ -4,7 +4,6 @@
|
||||
*
|
||||
*Do not manually edit these files, please find ngalert/api/swagger-codegen/ for commands on how to generate them.
|
||||
*/
|
||||
|
||||
package api
|
||||
|
||||
import (
|
||||
@ -32,7 +31,6 @@ func (f *ForkedTestingApi) RouteEvalQueries(ctx *models.ReqContext) response.Res
|
||||
}
|
||||
return f.forkRouteEvalQueries(ctx, conf)
|
||||
}
|
||||
|
||||
func (f *ForkedTestingApi) RouteTestRuleConfig(ctx *models.ReqContext) response.Response {
|
||||
conf := apimodels.TestRulePayload{}
|
||||
if err := web.Bind(ctx.Req, &conf); err != nil {
|
||||
@ -40,7 +38,6 @@ func (f *ForkedTestingApi) RouteTestRuleConfig(ctx *models.ReqContext) response.
|
||||
}
|
||||
return f.forkRouteTestRuleConfig(ctx, conf)
|
||||
}
|
||||
|
||||
func (f *ForkedTestingApi) RouteTestRuleGrafanaConfig(ctx *models.ReqContext) response.Response {
|
||||
conf := apimodels.TestRulePayload{}
|
||||
if err := web.Bind(ctx.Req, &conf); err != nil {
|
||||
|
@ -35,7 +35,7 @@ api.json: spec-stable.json
|
||||
go run cmd/clean-swagger/main.go -if $(<) -of $@
|
||||
|
||||
swagger-codegen-api:
|
||||
docker run --rm -v $$(pwd):/local --user $$(id -u):$$(id -g) swaggerapi/swagger-codegen-cli generate \
|
||||
docker run --rm -v $$(pwd):/local --user $$(id -u):$$(id -g) parsertongue/swagger-codegen-cli:3.0.32 generate \
|
||||
-i /local/post.json \
|
||||
-l go-server \
|
||||
-Dapis \
|
||||
@ -49,9 +49,9 @@ copy-files:
|
||||
ls -1 go | xargs -n 1 -I {} mv go/{} ../generated_base_{}
|
||||
|
||||
fix:
|
||||
sed -i -e 's/apimodels\.\[\]PostableAlert/apimodels.PostableAlerts/' $(GENERATED_GO_MATCHERS)
|
||||
sed -i -e 's/apimodels\.\[\]UpdateDashboardAclCommand/apimodels.Permissions/' $(GENERATED_GO_MATCHERS)
|
||||
sed -i -e 's/apimodels\.\[\]PostableApiReceiver/apimodels.TestReceiversConfigParams/' $(GENERATED_GO_MATCHERS)
|
||||
sed -i '' -e 's/apimodels\.\[\]PostableAlert/apimodels.PostableAlerts/' $(GENERATED_GO_MATCHERS)
|
||||
sed -i '' -e 's/apimodels\.\[\]UpdateDashboardAclCommand/apimodels.Permissions/' $(GENERATED_GO_MATCHERS)
|
||||
sed -i '' -e 's/apimodels\.\[\]PostableApiReceiver/apimodels.TestReceiversConfigParams/' $(GENERATED_GO_MATCHERS)
|
||||
goimports -w -v $(GENERATED_GO_MATCHERS)
|
||||
|
||||
clean:
|
||||
|
@ -0,0 +1,144 @@
|
||||
package definitions
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||
)
|
||||
|
||||
// swagger:route GET /api/provisioning/alert-rules/{UID} provisioning RouteGetAlertRule
|
||||
//
|
||||
// Get a specific alert rule by UID.
|
||||
//
|
||||
// Responses:
|
||||
// 200: AlertRule
|
||||
// 400: ValidationError
|
||||
|
||||
// swagger:route POST /api/provisioning/alert-rules provisioning RoutePostAlertRule
|
||||
//
|
||||
// Create a new alert rule.
|
||||
//
|
||||
// Responses:
|
||||
// 201: AlertRule
|
||||
// 400: ValidationError
|
||||
|
||||
// swagger:route PUT /api/provisioning/alert-rules/{UID} provisioning RoutePutAlertRule
|
||||
//
|
||||
// Update an existing alert rule.
|
||||
//
|
||||
// Consumes:
|
||||
// - application/json
|
||||
//
|
||||
// Responses:
|
||||
// 200: AlertRule
|
||||
// 400: ValidationError
|
||||
|
||||
// swagger:route DELETE /api/provisioning/alert-rules/{UID} provisioning RouteDeleteAlertRule
|
||||
//
|
||||
// Delete a specific alert rule by UID.
|
||||
//
|
||||
// Responses:
|
||||
// 204: description: The alert rule was deleted successfully.
|
||||
// 400: ValidationError
|
||||
|
||||
// swagger:parameters RouteGetAlertRule RoutePutAlertRule RouteDeleteAlertRule
|
||||
type AlertRuleUIDReference struct {
|
||||
// in:path
|
||||
UID string
|
||||
}
|
||||
|
||||
// swagger:parameters RoutePostAlertRule RoutePutAlertRule
|
||||
type AlertRulePayload struct {
|
||||
// in:body
|
||||
Body AlertRule
|
||||
}
|
||||
|
||||
type AlertRule struct {
|
||||
ID int64 `json:"id"`
|
||||
UID string `json:"uid"`
|
||||
OrgID int64 `json:"orgID"`
|
||||
FolderUID string `json:"folderUID"`
|
||||
RuleGroup string `json:"ruleGroup"`
|
||||
Title string `json:"title"`
|
||||
Condition string `json:"condition"`
|
||||
Data []models.AlertQuery `json:"data"`
|
||||
Updated time.Time `json:"updated,omitempty"`
|
||||
NoDataState models.NoDataState `json:"noDataState"`
|
||||
ExecErrState models.ExecutionErrorState `json:"execErrState"`
|
||||
For time.Duration `json:"for"`
|
||||
Annotations map[string]string `json:"annotations,omitempty"`
|
||||
Labels map[string]string `json:"labels,omitempty"`
|
||||
Provenance models.Provenance `json:"provenance,omitempty"`
|
||||
}
|
||||
|
||||
func (a *AlertRule) UpstreamModel() models.AlertRule {
|
||||
return models.AlertRule{
|
||||
ID: a.ID,
|
||||
UID: a.UID,
|
||||
OrgID: a.OrgID,
|
||||
NamespaceUID: a.FolderUID,
|
||||
RuleGroup: a.RuleGroup,
|
||||
Title: a.Title,
|
||||
Condition: a.Condition,
|
||||
Data: a.Data,
|
||||
Updated: a.Updated,
|
||||
NoDataState: a.NoDataState,
|
||||
ExecErrState: a.ExecErrState,
|
||||
For: a.For,
|
||||
Annotations: a.Annotations,
|
||||
Labels: a.Labels,
|
||||
}
|
||||
}
|
||||
|
||||
func NewAlertRule(rule models.AlertRule, provenance models.Provenance) AlertRule {
|
||||
return AlertRule{
|
||||
ID: rule.ID,
|
||||
UID: rule.UID,
|
||||
OrgID: rule.OrgID,
|
||||
FolderUID: rule.NamespaceUID,
|
||||
RuleGroup: rule.RuleGroup,
|
||||
Title: rule.Title,
|
||||
For: rule.For,
|
||||
Condition: rule.Condition,
|
||||
Data: rule.Data,
|
||||
Updated: rule.Updated,
|
||||
NoDataState: rule.NoDataState,
|
||||
ExecErrState: rule.ExecErrState,
|
||||
Annotations: rule.Annotations,
|
||||
Labels: rule.Labels,
|
||||
Provenance: provenance,
|
||||
}
|
||||
}
|
||||
|
||||
// swagger:route PUT /api/provisioning/folder/{FolderUID}/rule-groups/{Group} provisioning RoutePutAlertRuleGroup
|
||||
//
|
||||
// Update the interval of a rule group.
|
||||
//
|
||||
// Consumes:
|
||||
// - application/json
|
||||
//
|
||||
// Responses:
|
||||
// 200: AlertRuleGroup
|
||||
// 400: ValidationError
|
||||
|
||||
// swagger:parameters RoutePutAlertRuleGroup
|
||||
type FolderUIDPathParam struct {
|
||||
// in:path
|
||||
FolderUID string `json:"FolderUID"`
|
||||
}
|
||||
|
||||
// swagger:parameters RoutePutAlertRuleGroup
|
||||
type RuleGroupPathParam struct {
|
||||
// in:path
|
||||
Group string `json:"Group"`
|
||||
}
|
||||
|
||||
// swagger:parameters RoutePutAlertRuleGroup
|
||||
type AlertRuleGroupPayload struct {
|
||||
// in:body
|
||||
Body AlertRuleGroup
|
||||
}
|
||||
|
||||
type AlertRuleGroup struct {
|
||||
Interval int64 `json:"interval"`
|
||||
}
|
@ -194,6 +194,91 @@
|
||||
"type": "object",
|
||||
"x-go-package": "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
|
||||
},
|
||||
"AlertRule": {
|
||||
"properties": {
|
||||
"annotations": {
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "object",
|
||||
"x-go-name": "Annotations"
|
||||
},
|
||||
"condition": {
|
||||
"type": "string",
|
||||
"x-go-name": "Condition"
|
||||
},
|
||||
"data": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/AlertQuery"
|
||||
},
|
||||
"type": "array",
|
||||
"x-go-name": "Data"
|
||||
},
|
||||
"execErrState": {
|
||||
"$ref": "#/definitions/ExecutionErrorState"
|
||||
},
|
||||
"folderUID": {
|
||||
"type": "string",
|
||||
"x-go-name": "FolderUID"
|
||||
},
|
||||
"for": {
|
||||
"$ref": "#/definitions/Duration"
|
||||
},
|
||||
"id": {
|
||||
"format": "int64",
|
||||
"type": "integer",
|
||||
"x-go-name": "ID"
|
||||
},
|
||||
"labels": {
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "object",
|
||||
"x-go-name": "Labels"
|
||||
},
|
||||
"noDataState": {
|
||||
"$ref": "#/definitions/NoDataState"
|
||||
},
|
||||
"orgID": {
|
||||
"format": "int64",
|
||||
"type": "integer",
|
||||
"x-go-name": "OrgID"
|
||||
},
|
||||
"provenance": {
|
||||
"$ref": "#/definitions/Provenance"
|
||||
},
|
||||
"ruleGroup": {
|
||||
"type": "string",
|
||||
"x-go-name": "RuleGroup"
|
||||
},
|
||||
"title": {
|
||||
"type": "string",
|
||||
"x-go-name": "Title"
|
||||
},
|
||||
"uid": {
|
||||
"type": "string",
|
||||
"x-go-name": "UID"
|
||||
},
|
||||
"updated": {
|
||||
"format": "date-time",
|
||||
"type": "string",
|
||||
"x-go-name": "Updated"
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"x-go-package": "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
|
||||
},
|
||||
"AlertRuleGroup": {
|
||||
"properties": {
|
||||
"interval": {
|
||||
"format": "int64",
|
||||
"type": "integer",
|
||||
"x-go-name": "Interval"
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"x-go-package": "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
|
||||
},
|
||||
"AlertingRule": {
|
||||
"description": "adapted from cortex",
|
||||
"properties": {
|
||||
@ -663,6 +748,10 @@
|
||||
"x-go-package": "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
|
||||
},
|
||||
"EvalQueriesResponse": {},
|
||||
"ExecutionErrorState": {
|
||||
"type": "string",
|
||||
"x-go-package": "github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||
},
|
||||
"ExtendedReceiver": {
|
||||
"properties": {
|
||||
"email_configs": {
|
||||
@ -1456,6 +1545,10 @@
|
||||
"type": "object",
|
||||
"x-go-package": "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
|
||||
},
|
||||
"NoDataState": {
|
||||
"type": "string",
|
||||
"x-go-package": "github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||
},
|
||||
"NotFound": {
|
||||
"type": "object",
|
||||
"x-go-package": "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
|
||||
@ -2923,6 +3016,7 @@
|
||||
"x-go-package": "github.com/prometheus/alertmanager/timeinterval"
|
||||
},
|
||||
"URL": {
|
||||
"description": "The general form represented is:\n\n[scheme:][//[userinfo@]host][/]path[?query][#fragment]\n\nURLs that do not start with a slash after the scheme are interpreted as:\n\nscheme:opaque[?query][#fragment]\n\nNote that the Path field is stored in decoded form: /%47%6f%2f becomes /Go/.\nA consequence is that it is impossible to tell which slashes in the Path were\nslashes in the raw URL and which were %2f. This distinction is rarely important,\nbut when it is, the code should use RawPath, an optional field which only gets\nset if the default encoding is different from Path.\n\nURL's String method uses the EscapedPath method to obtain the path. See the\nEscapedPath method for more details.",
|
||||
"properties": {
|
||||
"ForceQuery": {
|
||||
"type": "boolean"
|
||||
@ -2955,9 +3049,9 @@
|
||||
"$ref": "#/definitions/Userinfo"
|
||||
}
|
||||
},
|
||||
"title": "URL is a custom URL type that allows validation at configuration load time.",
|
||||
"title": "A URL represents a parsed URL (technically, a URI reference).",
|
||||
"type": "object",
|
||||
"x-go-package": "github.com/prometheus/common/config"
|
||||
"x-go-package": "net/url"
|
||||
},
|
||||
"Userinfo": {
|
||||
"description": "The Userinfo type is an immutable encapsulation of username and\npassword details for a URL. An existing Userinfo value is guaranteed\nto have a username set (potentially empty, as allowed by RFC 2396),\nand optionally a password.",
|
||||
@ -3179,12 +3273,11 @@
|
||||
"type": "object"
|
||||
},
|
||||
"alertGroups": {
|
||||
"description": "AlertGroups alert groups",
|
||||
"items": {
|
||||
"$ref": "#/definitions/alertGroup"
|
||||
},
|
||||
"type": "array",
|
||||
"x-go-name": "AlertGroups",
|
||||
"x-go-package": "github.com/prometheus/alertmanager/api/v2/models"
|
||||
"type": "array"
|
||||
},
|
||||
"alertStatus": {
|
||||
"description": "AlertStatus alert status",
|
||||
@ -3304,6 +3397,7 @@
|
||||
"$ref": "#/definitions/Duration"
|
||||
},
|
||||
"gettableAlert": {
|
||||
"description": "GettableAlert gettable alert",
|
||||
"properties": {
|
||||
"annotations": {
|
||||
"$ref": "#/definitions/labelSet"
|
||||
@ -3362,9 +3456,7 @@
|
||||
"status",
|
||||
"updatedAt"
|
||||
],
|
||||
"type": "object",
|
||||
"x-go-name": "GettableAlert",
|
||||
"x-go-package": "github.com/prometheus/alertmanager/api/v2/models"
|
||||
"type": "object"
|
||||
},
|
||||
"gettableAlerts": {
|
||||
"description": "GettableAlerts gettable alerts",
|
||||
@ -3374,7 +3466,6 @@
|
||||
"type": "array"
|
||||
},
|
||||
"gettableSilence": {
|
||||
"description": "GettableSilence gettable silence",
|
||||
"properties": {
|
||||
"comment": {
|
||||
"description": "comment",
|
||||
@ -3426,7 +3517,9 @@
|
||||
"status",
|
||||
"updatedAt"
|
||||
],
|
||||
"type": "object"
|
||||
"type": "object",
|
||||
"x-go-name": "GettableSilence",
|
||||
"x-go-package": "github.com/prometheus/alertmanager/api/v2/models"
|
||||
},
|
||||
"gettableSilences": {
|
||||
"items": {
|
||||
@ -3563,6 +3656,7 @@
|
||||
"x-go-package": "github.com/prometheus/alertmanager/api/v2/models"
|
||||
},
|
||||
"postableSilence": {
|
||||
"description": "PostableSilence postable silence",
|
||||
"properties": {
|
||||
"comment": {
|
||||
"description": "comment",
|
||||
@ -3602,11 +3696,10 @@
|
||||
"matchers",
|
||||
"startsAt"
|
||||
],
|
||||
"type": "object",
|
||||
"x-go-name": "PostableSilence",
|
||||
"x-go-package": "github.com/prometheus/alertmanager/api/v2/models"
|
||||
"type": "object"
|
||||
},
|
||||
"receiver": {
|
||||
"description": "Receiver receiver",
|
||||
"properties": {
|
||||
"name": {
|
||||
"description": "name",
|
||||
@ -3617,9 +3710,7 @@
|
||||
"required": [
|
||||
"name"
|
||||
],
|
||||
"type": "object",
|
||||
"x-go-name": "Receiver",
|
||||
"x-go-package": "github.com/prometheus/alertmanager/api/v2/models"
|
||||
"type": "object"
|
||||
},
|
||||
"silence": {
|
||||
"description": "Silence silence",
|
||||
@ -4838,6 +4929,134 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/provisioning/alert-rules": {
|
||||
"post": {
|
||||
"operationId": "RoutePostAlertRule",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "body",
|
||||
"name": "Body",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/AlertRule"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "AlertRule",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/AlertRule"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "ValidationError",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/ValidationError"
|
||||
}
|
||||
}
|
||||
},
|
||||
"summary": "Create a new alert rule.",
|
||||
"tags": [
|
||||
"provisioning"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/provisioning/alert-rules/{UID}": {
|
||||
"delete": {
|
||||
"operationId": "RouteDeleteAlertRule",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "path",
|
||||
"name": "UID",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"204": {
|
||||
"description": " The alert rule was deleted successfully."
|
||||
},
|
||||
"400": {
|
||||
"description": "ValidationError",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/ValidationError"
|
||||
}
|
||||
}
|
||||
},
|
||||
"summary": "Delete a specific alert rule by UID.",
|
||||
"tags": [
|
||||
"provisioning"
|
||||
]
|
||||
},
|
||||
"get": {
|
||||
"operationId": "RouteGetAlertRule",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "path",
|
||||
"name": "UID",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "AlertRule",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/AlertRule"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "ValidationError",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/ValidationError"
|
||||
}
|
||||
}
|
||||
},
|
||||
"summary": "Get a specific alert rule by UID.",
|
||||
"tags": [
|
||||
"provisioning"
|
||||
]
|
||||
},
|
||||
"put": {
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"operationId": "RoutePutAlertRule",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "path",
|
||||
"name": "UID",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"in": "body",
|
||||
"name": "Body",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/AlertRule"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "AlertRule",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/AlertRule"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "ValidationError",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/ValidationError"
|
||||
}
|
||||
}
|
||||
},
|
||||
"summary": "Update an existing alert rule.",
|
||||
"tags": [
|
||||
"provisioning"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/provisioning/contact-points": {
|
||||
"get": {
|
||||
"operationId": "RouteGetContactpoints",
|
||||
@ -4969,6 +5188,53 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/provisioning/folder/{FolderUID}/rule-groups/{Group}": {
|
||||
"put": {
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"operationId": "RoutePutAlertRuleGroup",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "path",
|
||||
"name": "FolderUID",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"in": "path",
|
||||
"name": "Group",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"in": "body",
|
||||
"name": "Body",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/AlertRuleGroup"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "AlertRuleGroup",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/AlertRuleGroup"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "ValidationError",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/ValidationError"
|
||||
}
|
||||
}
|
||||
},
|
||||
"summary": "Update the interval of an rule group.",
|
||||
"tags": [
|
||||
"provisioning"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/provisioning/mute-timings": {
|
||||
"get": {
|
||||
"operationId": "RouteGetMuteTimings",
|
||||
|
@ -1122,6 +1122,134 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/provisioning/alert-rules": {
|
||||
"post": {
|
||||
"tags": [
|
||||
"provisioning"
|
||||
],
|
||||
"summary": "Create a new alert rule.",
|
||||
"operationId": "RoutePostAlertRule",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "Body",
|
||||
"in": "body",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/AlertRule"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "AlertRule",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/AlertRule"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "ValidationError",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/ValidationError"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/provisioning/alert-rules/{UID}": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"provisioning"
|
||||
],
|
||||
"summary": "Get a specific alert rule by UID.",
|
||||
"operationId": "RouteGetAlertRule",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"name": "UID",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "AlertRule",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/AlertRule"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "ValidationError",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/ValidationError"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"put": {
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"provisioning"
|
||||
],
|
||||
"summary": "Update an existing alert rule.",
|
||||
"operationId": "RoutePutAlertRule",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"name": "UID",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "Body",
|
||||
"in": "body",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/AlertRule"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "AlertRule",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/AlertRule"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "ValidationError",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/ValidationError"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"delete": {
|
||||
"tags": [
|
||||
"provisioning"
|
||||
],
|
||||
"summary": "Delete a specific alert rule by UID.",
|
||||
"operationId": "RouteDeleteAlertRule",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"name": "UID",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"204": {
|
||||
"description": " The alert rule was deleted successfully."
|
||||
},
|
||||
"400": {
|
||||
"description": "ValidationError",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/ValidationError"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/provisioning/contact-points": {
|
||||
"get": {
|
||||
"tags": [
|
||||
@ -1253,6 +1381,53 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/provisioning/folder/{FolderUID}/rule-groups/{Group}": {
|
||||
"put": {
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"provisioning"
|
||||
],
|
||||
"summary": "Update the interval of an rule group.",
|
||||
"operationId": "RoutePutAlertRuleGroup",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"name": "FolderUID",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "Group",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "Body",
|
||||
"in": "body",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/AlertRuleGroup"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "AlertRuleGroup",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/AlertRuleGroup"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "ValidationError",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/ValidationError"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/provisioning/mute-timings": {
|
||||
"get": {
|
||||
"tags": [
|
||||
@ -2394,6 +2569,91 @@
|
||||
},
|
||||
"x-go-package": "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
|
||||
},
|
||||
"AlertRule": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"annotations": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
},
|
||||
"x-go-name": "Annotations"
|
||||
},
|
||||
"condition": {
|
||||
"type": "string",
|
||||
"x-go-name": "Condition"
|
||||
},
|
||||
"data": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/AlertQuery"
|
||||
},
|
||||
"x-go-name": "Data"
|
||||
},
|
||||
"execErrState": {
|
||||
"$ref": "#/definitions/ExecutionErrorState"
|
||||
},
|
||||
"folderUID": {
|
||||
"type": "string",
|
||||
"x-go-name": "FolderUID"
|
||||
},
|
||||
"for": {
|
||||
"$ref": "#/definitions/Duration"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"x-go-name": "ID"
|
||||
},
|
||||
"labels": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
},
|
||||
"x-go-name": "Labels"
|
||||
},
|
||||
"noDataState": {
|
||||
"$ref": "#/definitions/NoDataState"
|
||||
},
|
||||
"orgID": {
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"x-go-name": "OrgID"
|
||||
},
|
||||
"provenance": {
|
||||
"$ref": "#/definitions/Provenance"
|
||||
},
|
||||
"ruleGroup": {
|
||||
"type": "string",
|
||||
"x-go-name": "RuleGroup"
|
||||
},
|
||||
"title": {
|
||||
"type": "string",
|
||||
"x-go-name": "Title"
|
||||
},
|
||||
"uid": {
|
||||
"type": "string",
|
||||
"x-go-name": "UID"
|
||||
},
|
||||
"updated": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"x-go-name": "Updated"
|
||||
}
|
||||
},
|
||||
"x-go-package": "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
|
||||
},
|
||||
"AlertRuleGroup": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"interval": {
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"x-go-name": "Interval"
|
||||
}
|
||||
},
|
||||
"x-go-package": "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
|
||||
},
|
||||
"AlertingRule": {
|
||||
"description": "adapted from cortex",
|
||||
"type": "object",
|
||||
@ -2866,6 +3126,10 @@
|
||||
"EvalQueriesResponse": {
|
||||
"$ref": "#/definitions/EvalQueriesResponse"
|
||||
},
|
||||
"ExecutionErrorState": {
|
||||
"type": "string",
|
||||
"x-go-package": "github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||
},
|
||||
"ExtendedReceiver": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@ -3660,6 +3924,10 @@
|
||||
},
|
||||
"x-go-package": "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
|
||||
},
|
||||
"NoDataState": {
|
||||
"type": "string",
|
||||
"x-go-package": "github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||
},
|
||||
"NotFound": {
|
||||
"type": "object",
|
||||
"x-go-package": "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
|
||||
@ -5127,8 +5395,9 @@
|
||||
"x-go-package": "github.com/prometheus/alertmanager/timeinterval"
|
||||
},
|
||||
"URL": {
|
||||
"description": "The general form represented is:\n\n[scheme:][//[userinfo@]host][/]path[?query][#fragment]\n\nURLs that do not start with a slash after the scheme are interpreted as:\n\nscheme:opaque[?query][#fragment]\n\nNote that the Path field is stored in decoded form: /%47%6f%2f becomes /Go/.\nA consequence is that it is impossible to tell which slashes in the Path were\nslashes in the raw URL and which were %2f. This distinction is rarely important,\nbut when it is, the code should use RawPath, an optional field which only gets\nset if the default encoding is different from Path.\n\nURL's String method uses the EscapedPath method to obtain the path. See the\nEscapedPath method for more details.",
|
||||
"type": "object",
|
||||
"title": "URL is a custom URL type that allows validation at configuration load time.",
|
||||
"title": "A URL represents a parsed URL (technically, a URI reference).",
|
||||
"properties": {
|
||||
"ForceQuery": {
|
||||
"type": "boolean"
|
||||
@ -5161,7 +5430,7 @@
|
||||
"$ref": "#/definitions/Userinfo"
|
||||
}
|
||||
},
|
||||
"x-go-package": "github.com/prometheus/common/config"
|
||||
"x-go-package": "net/url"
|
||||
},
|
||||
"Userinfo": {
|
||||
"description": "The Userinfo type is an immutable encapsulation of username and\npassword details for a URL. An existing Userinfo value is guaranteed\nto have a username set (potentially empty, as allowed by RFC 2396),\nand optionally a password.",
|
||||
@ -5384,12 +5653,11 @@
|
||||
"$ref": "#/definitions/alertGroup"
|
||||
},
|
||||
"alertGroups": {
|
||||
"description": "AlertGroups alert groups",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/alertGroup"
|
||||
},
|
||||
"x-go-name": "AlertGroups",
|
||||
"x-go-package": "github.com/prometheus/alertmanager/api/v2/models",
|
||||
"$ref": "#/definitions/alertGroups"
|
||||
},
|
||||
"alertStatus": {
|
||||
@ -5510,6 +5778,7 @@
|
||||
"$ref": "#/definitions/Duration"
|
||||
},
|
||||
"gettableAlert": {
|
||||
"description": "GettableAlert gettable alert",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"labels",
|
||||
@ -5569,8 +5838,6 @@
|
||||
"x-go-name": "UpdatedAt"
|
||||
}
|
||||
},
|
||||
"x-go-name": "GettableAlert",
|
||||
"x-go-package": "github.com/prometheus/alertmanager/api/v2/models",
|
||||
"$ref": "#/definitions/gettableAlert"
|
||||
},
|
||||
"gettableAlerts": {
|
||||
@ -5582,7 +5849,6 @@
|
||||
"$ref": "#/definitions/gettableAlerts"
|
||||
},
|
||||
"gettableSilence": {
|
||||
"description": "GettableSilence gettable silence",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"comment",
|
||||
@ -5635,6 +5901,8 @@
|
||||
"x-go-name": "UpdatedAt"
|
||||
}
|
||||
},
|
||||
"x-go-name": "GettableSilence",
|
||||
"x-go-package": "github.com/prometheus/alertmanager/api/v2/models",
|
||||
"$ref": "#/definitions/gettableSilence"
|
||||
},
|
||||
"gettableSilences": {
|
||||
@ -5773,6 +6041,7 @@
|
||||
"x-go-package": "github.com/prometheus/alertmanager/api/v2/models"
|
||||
},
|
||||
"postableSilence": {
|
||||
"description": "PostableSilence postable silence",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"comment",
|
||||
@ -5813,11 +6082,10 @@
|
||||
"x-go-name": "StartsAt"
|
||||
}
|
||||
},
|
||||
"x-go-name": "PostableSilence",
|
||||
"x-go-package": "github.com/prometheus/alertmanager/api/v2/models",
|
||||
"$ref": "#/definitions/postableSilence"
|
||||
},
|
||||
"receiver": {
|
||||
"description": "Receiver receiver",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name"
|
||||
@ -5829,8 +6097,6 @@
|
||||
"x-go-name": "Name"
|
||||
}
|
||||
},
|
||||
"x-go-name": "Receiver",
|
||||
"x-go-package": "github.com/prometheus/alertmanager/api/v2/models",
|
||||
"$ref": "#/definitions/receiver"
|
||||
},
|
||||
"silence": {
|
||||
|
@ -157,6 +157,7 @@ func (ng *AlertNG) init() error {
|
||||
contactPointService := provisioning.NewContactPointService(store, ng.SecretsService, store, store, ng.Log)
|
||||
templateService := provisioning.NewTemplateService(store, store, store, ng.Log)
|
||||
muteTimingService := provisioning.NewMuteTimingService(store, store, store, ng.Log)
|
||||
alertRuleService := provisioning.NewAlertRuleService(store, store, store, int64(ng.Cfg.UnifiedAlerting.DefaultRuleEvaluationInterval.Seconds()), ng.Log)
|
||||
|
||||
api := api.API{
|
||||
Cfg: ng.Cfg,
|
||||
@ -180,6 +181,7 @@ func (ng *AlertNG) init() error {
|
||||
ContactPointService: contactPointService,
|
||||
Templates: templateService,
|
||||
MuteTimings: muteTimingService,
|
||||
AlertRules: alertRuleService,
|
||||
}
|
||||
api.RegisterAPIEndpoints(ng.Metrics.GetAPIMetrics())
|
||||
|
||||
|
151
pkg/services/ngalert/provisioning/alert_rules.go
Normal file
151
pkg/services/ngalert/provisioning/alert_rules.go
Normal file
@ -0,0 +1,151 @@
|
||||
package provisioning
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/store"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
)
|
||||
|
||||
type AlertRuleService struct {
|
||||
defaultInterval int64
|
||||
ruleStore store.RuleStore
|
||||
provenanceStore ProvisioningStore
|
||||
xact TransactionManager
|
||||
log log.Logger
|
||||
}
|
||||
|
||||
func NewAlertRuleService(ruleStore store.RuleStore,
|
||||
provenanceStore ProvisioningStore,
|
||||
xact TransactionManager,
|
||||
defaultInterval int64,
|
||||
log log.Logger) *AlertRuleService {
|
||||
return &AlertRuleService{
|
||||
defaultInterval: defaultInterval,
|
||||
ruleStore: ruleStore,
|
||||
provenanceStore: provenanceStore,
|
||||
xact: xact,
|
||||
log: log,
|
||||
}
|
||||
}
|
||||
|
||||
func (service *AlertRuleService) GetAlertRule(ctx context.Context, orgID int64, ruleUID string) (models.AlertRule, models.Provenance, error) {
|
||||
query := &models.GetAlertRuleByUIDQuery{
|
||||
OrgID: orgID,
|
||||
UID: ruleUID,
|
||||
}
|
||||
err := service.ruleStore.GetAlertRuleByUID(ctx, query)
|
||||
if err != nil {
|
||||
return models.AlertRule{}, models.ProvenanceNone, err
|
||||
}
|
||||
provenance, err := service.provenanceStore.GetProvenance(ctx, query.Result, orgID)
|
||||
if err != nil {
|
||||
return models.AlertRule{}, models.ProvenanceNone, err
|
||||
}
|
||||
return *query.Result, provenance, nil
|
||||
}
|
||||
|
||||
func (service *AlertRuleService) CreateAlertRule(ctx context.Context, rule models.AlertRule, provenance models.Provenance) (models.AlertRule, error) {
|
||||
if rule.UID == "" {
|
||||
rule.UID = util.GenerateShortUID()
|
||||
}
|
||||
interval, err := service.ruleStore.GetRuleGroupInterval(ctx, rule.OrgID, rule.NamespaceUID, rule.RuleGroup)
|
||||
// if the alert group does not exists we just use the default interval
|
||||
if err != nil && errors.Is(err, store.ErrAlertRuleGroupNotFound) {
|
||||
interval = service.defaultInterval
|
||||
} else if err != nil {
|
||||
return models.AlertRule{}, err
|
||||
}
|
||||
rule.IntervalSeconds = interval
|
||||
rule.Updated = time.Now()
|
||||
err = service.xact.InTransaction(ctx, func(ctx context.Context) error {
|
||||
ids, err := service.ruleStore.InsertAlertRules(ctx, []models.AlertRule{
|
||||
rule,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if id, ok := ids[rule.UID]; ok {
|
||||
rule.ID = id
|
||||
} else {
|
||||
return errors.New("couldn't find newly created id")
|
||||
}
|
||||
err = service.ruleStore.UpdateRuleGroup(ctx, rule.OrgID, rule.NamespaceUID, rule.RuleGroup, rule.IntervalSeconds)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return service.provenanceStore.SetProvenance(ctx, &rule, rule.OrgID, provenance)
|
||||
})
|
||||
if err != nil {
|
||||
return models.AlertRule{}, err
|
||||
}
|
||||
return rule, nil
|
||||
}
|
||||
|
||||
func (service *AlertRuleService) UpdateAlertRule(ctx context.Context, rule models.AlertRule, provenance models.Provenance) (models.AlertRule, error) {
|
||||
storedRule, storedProvenance, err := service.GetAlertRule(ctx, rule.OrgID, rule.UID)
|
||||
if err != nil {
|
||||
return models.AlertRule{}, err
|
||||
}
|
||||
if storedProvenance != provenance && storedProvenance != models.ProvenanceNone {
|
||||
return models.AlertRule{}, fmt.Errorf("cannot changed provenance from '%s' to '%s'", storedProvenance, provenance)
|
||||
}
|
||||
rule.Updated = time.Now()
|
||||
rule.ID = storedRule.ID
|
||||
rule.IntervalSeconds, err = service.ruleStore.GetRuleGroupInterval(ctx, rule.OrgID, rule.NamespaceUID, rule.RuleGroup)
|
||||
if err != nil {
|
||||
return models.AlertRule{}, err
|
||||
}
|
||||
service.log.Info("update rule", "ID", storedRule.ID, "labels", fmt.Sprintf("%+v", rule.Labels))
|
||||
err = service.xact.InTransaction(ctx, func(ctx context.Context) error {
|
||||
err := service.ruleStore.UpdateAlertRules(ctx, []store.UpdateRule{
|
||||
{
|
||||
Existing: &storedRule,
|
||||
New: rule,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = service.ruleStore.UpdateRuleGroup(ctx, rule.OrgID, rule.NamespaceUID, rule.RuleGroup, rule.IntervalSeconds)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return service.provenanceStore.SetProvenance(ctx, &rule, rule.OrgID, provenance)
|
||||
})
|
||||
if err != nil {
|
||||
return models.AlertRule{}, err
|
||||
}
|
||||
return rule, err
|
||||
}
|
||||
|
||||
func (service *AlertRuleService) DeleteAlertRule(ctx context.Context, orgID int64, ruleUID string, provenance models.Provenance) error {
|
||||
rule := &models.AlertRule{
|
||||
OrgID: orgID,
|
||||
UID: ruleUID,
|
||||
}
|
||||
// check that provenance is not changed in a invalid way
|
||||
storedProvenance, err := service.provenanceStore.GetProvenance(ctx, rule, rule.OrgID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if storedProvenance != provenance && storedProvenance != models.ProvenanceNone {
|
||||
return fmt.Errorf("cannot delete with provided provenance '%s', needs '%s'", provenance, storedProvenance)
|
||||
}
|
||||
return service.xact.InTransaction(ctx, func(ctx context.Context) error {
|
||||
err := service.ruleStore.DeleteAlertRulesByUID(ctx, orgID, ruleUID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return service.provenanceStore.DeleteProvenance(ctx, rule, rule.OrgID)
|
||||
})
|
||||
}
|
||||
|
||||
func (service *AlertRuleService) UpdateAlertGroup(ctx context.Context, orgID int64, folderUID, roulegroup string, interval int64) error {
|
||||
return service.ruleStore.UpdateRuleGroup(ctx, orgID, folderUID, roulegroup, interval)
|
||||
}
|
166
pkg/services/ngalert/provisioning/alert_rules_test.go
Normal file
166
pkg/services/ngalert/provisioning/alert_rules_test.go
Normal file
@ -0,0 +1,166 @@
|
||||
package provisioning
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/store"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestAlertRuleService(t *testing.T) {
|
||||
ruleService := createAlertRuleService(t)
|
||||
t.Run("alert rule creation should return the created id", func(t *testing.T) {
|
||||
var orgID int64 = 1
|
||||
rule, err := ruleService.CreateAlertRule(context.Background(), dummyRule("test#1", orgID), models.ProvenanceNone)
|
||||
require.NoError(t, err)
|
||||
require.NotEqual(t, 0, rule.ID, "expected to get the created id and not the zero value")
|
||||
})
|
||||
t.Run("alert rule creation should set the right provenance", func(t *testing.T) {
|
||||
var orgID int64 = 1
|
||||
rule, err := ruleService.CreateAlertRule(context.Background(), dummyRule("test#2", orgID), models.ProvenanceAPI)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, provenance, err := ruleService.GetAlertRule(context.Background(), orgID, rule.UID)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, models.ProvenanceAPI, provenance)
|
||||
})
|
||||
t.Run("alert rule group should be updated correctly", func(t *testing.T) {
|
||||
var orgID int64 = 1
|
||||
rule := dummyRule("test#3", orgID)
|
||||
rule.RuleGroup = "a"
|
||||
rule, err := ruleService.CreateAlertRule(context.Background(), rule, models.ProvenanceNone)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int64(60), rule.IntervalSeconds)
|
||||
|
||||
var interval int64 = 120
|
||||
err = ruleService.UpdateAlertGroup(context.Background(), orgID, rule.NamespaceUID, rule.RuleGroup, 120)
|
||||
require.NoError(t, err)
|
||||
|
||||
rule, _, err = ruleService.GetAlertRule(context.Background(), orgID, rule.UID)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, interval, rule.IntervalSeconds)
|
||||
})
|
||||
t.Run("alert rule should get interval from existing rule group", func(t *testing.T) {
|
||||
var orgID int64 = 1
|
||||
rule := dummyRule("test#4", orgID)
|
||||
rule.RuleGroup = "b"
|
||||
rule, err := ruleService.CreateAlertRule(context.Background(), rule, models.ProvenanceNone)
|
||||
require.NoError(t, err)
|
||||
|
||||
var interval int64 = 120
|
||||
err = ruleService.UpdateAlertGroup(context.Background(), orgID, rule.NamespaceUID, rule.RuleGroup, 120)
|
||||
require.NoError(t, err)
|
||||
|
||||
rule = dummyRule("test#4-1", orgID)
|
||||
rule.RuleGroup = "b"
|
||||
rule, err = ruleService.CreateAlertRule(context.Background(), rule, models.ProvenanceNone)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, interval, rule.IntervalSeconds)
|
||||
})
|
||||
t.Run("alert rule provenace should be correctly checked", func(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
from models.Provenance
|
||||
to models.Provenance
|
||||
errNil bool
|
||||
}{
|
||||
{
|
||||
name: "should be able to update from provenance none to api",
|
||||
from: models.ProvenanceNone,
|
||||
to: models.ProvenanceAPI,
|
||||
errNil: true,
|
||||
},
|
||||
{
|
||||
name: "should be able to update from provenance none to file",
|
||||
from: models.ProvenanceNone,
|
||||
to: models.ProvenanceFile,
|
||||
errNil: true,
|
||||
},
|
||||
{
|
||||
name: "should not be able to update from provenance api to file",
|
||||
from: models.ProvenanceAPI,
|
||||
to: models.ProvenanceFile,
|
||||
errNil: false,
|
||||
},
|
||||
{
|
||||
name: "should not be able to update from provenance api to none",
|
||||
from: models.ProvenanceAPI,
|
||||
to: models.ProvenanceNone,
|
||||
errNil: false,
|
||||
},
|
||||
{
|
||||
name: "should not be able to update from provenance file to api",
|
||||
from: models.ProvenanceFile,
|
||||
to: models.ProvenanceAPI,
|
||||
errNil: false,
|
||||
},
|
||||
{
|
||||
name: "should not be able to update from provenance file to none",
|
||||
from: models.ProvenanceFile,
|
||||
to: models.ProvenanceNone,
|
||||
errNil: false,
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
var orgID int64 = 1
|
||||
rule := dummyRule(t.Name(), orgID)
|
||||
rule, err := ruleService.CreateAlertRule(context.Background(), rule, test.from)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = ruleService.UpdateAlertRule(context.Background(), rule, test.to)
|
||||
if test.errNil {
|
||||
require.NoError(t, err)
|
||||
} else {
|
||||
require.Error(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func createAlertRuleService(t *testing.T) AlertRuleService {
|
||||
t.Helper()
|
||||
sqlStore := sqlstore.InitTestDB(t)
|
||||
store := store.DBstore{
|
||||
SQLStore: sqlStore,
|
||||
BaseInterval: time.Second * 10,
|
||||
}
|
||||
return AlertRuleService{
|
||||
ruleStore: store,
|
||||
provenanceStore: store,
|
||||
xact: sqlStore,
|
||||
log: log.New("testing"),
|
||||
defaultInterval: 60,
|
||||
}
|
||||
}
|
||||
|
||||
func dummyRule(title string, orgID int64) models.AlertRule {
|
||||
return models.AlertRule{
|
||||
OrgID: orgID,
|
||||
Title: title,
|
||||
Condition: "A",
|
||||
Version: 1,
|
||||
IntervalSeconds: 60,
|
||||
Data: []models.AlertQuery{
|
||||
{
|
||||
RefID: "A",
|
||||
Model: json.RawMessage("{}"),
|
||||
RelativeTimeRange: models.RelativeTimeRange{
|
||||
From: models.Duration(60),
|
||||
To: models.Duration(0),
|
||||
},
|
||||
},
|
||||
},
|
||||
RuleGroup: "my-cool-group",
|
||||
For: time.Second * 60,
|
||||
NoDataState: models.OK,
|
||||
ExecErrState: models.OkErrState,
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@ package store
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
@ -32,6 +33,10 @@ type UpdateRule struct {
|
||||
New ngmodels.AlertRule
|
||||
}
|
||||
|
||||
var (
|
||||
ErrAlertRuleGroupNotFound = errors.New("rulegroup not found")
|
||||
)
|
||||
|
||||
// RuleStore is the interface for persisting alert rules and instances
|
||||
type RuleStore interface {
|
||||
DeleteAlertRulesByUID(ctx context.Context, orgID int64, ruleUID ...string) error
|
||||
@ -42,9 +47,14 @@ type RuleStore interface {
|
||||
ListAlertRules(ctx context.Context, query *ngmodels.ListAlertRulesQuery) error
|
||||
// GetRuleGroups returns the unique rule groups across all organizations.
|
||||
GetRuleGroups(ctx context.Context, query *ngmodels.ListRuleGroupsQuery) error
|
||||
GetRuleGroupInterval(ctx context.Context, orgID int64, namespaceUID string, ruleGroup string) (int64, error)
|
||||
// UpdateRuleGroup will update the interval for all rules in the group.
|
||||
UpdateRuleGroup(ctx context.Context, orgID int64, namespaceUID string, ruleGroup string, interval int64) error
|
||||
GetUserVisibleNamespaces(context.Context, int64, *models.SignedInUser) (map[string]*models.Folder, error)
|
||||
GetNamespaceByTitle(context.Context, string, int64, *models.SignedInUser, bool) (*models.Folder, error)
|
||||
InsertAlertRules(ctx context.Context, rule []ngmodels.AlertRule) error
|
||||
// InsertAlertRules will insert all alert rules passed into the function
|
||||
// and return the map of uuid to id.
|
||||
InsertAlertRules(ctx context.Context, rule []ngmodels.AlertRule) (map[string]int64, error)
|
||||
UpdateAlertRules(ctx context.Context, rule []UpdateRule) error
|
||||
}
|
||||
|
||||
@ -127,17 +137,20 @@ func (st DBstore) GetAlertRulesGroupByRuleUID(ctx context.Context, query *ngmode
|
||||
}
|
||||
|
||||
// InsertAlertRules is a handler for creating/updating alert rules.
|
||||
func (st DBstore) InsertAlertRules(ctx context.Context, rules []ngmodels.AlertRule) error {
|
||||
return st.SQLStore.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error {
|
||||
func (st DBstore) InsertAlertRules(ctx context.Context, rules []ngmodels.AlertRule) (map[string]int64, error) {
|
||||
ids := make(map[string]int64, len(rules))
|
||||
return ids, st.SQLStore.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error {
|
||||
newRules := make([]ngmodels.AlertRule, 0, len(rules))
|
||||
ruleVersions := make([]ngmodels.AlertRuleVersion, 0, len(rules))
|
||||
for i := range rules {
|
||||
r := rules[i]
|
||||
if r.UID == "" {
|
||||
uid, err := GenerateNewAlertRuleUID(sess, r.OrgID, r.Title)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to generate UID for alert rule %q: %w", r.Title, err)
|
||||
}
|
||||
r.UID = uid
|
||||
}
|
||||
r.Version = 1
|
||||
if err := st.validateAlertRule(r); err != nil {
|
||||
return err
|
||||
@ -147,8 +160,8 @@ func (st DBstore) InsertAlertRules(ctx context.Context, rules []ngmodels.AlertRu
|
||||
}
|
||||
newRules = append(newRules, r)
|
||||
ruleVersions = append(ruleVersions, ngmodels.AlertRuleVersion{
|
||||
RuleOrgID: r.OrgID,
|
||||
RuleUID: r.UID,
|
||||
RuleOrgID: r.OrgID,
|
||||
RuleNamespaceUID: r.NamespaceUID,
|
||||
RuleGroup: r.RuleGroup,
|
||||
ParentVersion: 0,
|
||||
@ -166,12 +179,17 @@ func (st DBstore) InsertAlertRules(ctx context.Context, rules []ngmodels.AlertRu
|
||||
})
|
||||
}
|
||||
if len(newRules) > 0 {
|
||||
if _, err := sess.Insert(&newRules); err != nil {
|
||||
// we have to insert the rules one by one as otherwise we are
|
||||
// not able to fetch the inserted id as it's not supported by xorm
|
||||
for i := range newRules {
|
||||
if _, err := sess.Insert(&newRules[i]); err != nil {
|
||||
if st.SQLStore.Dialect.IsUniqueConstraintViolation(err) {
|
||||
return ngmodels.ErrAlertRuleUniqueConstraintViolation
|
||||
}
|
||||
return fmt.Errorf("failed to create new rules: %w", err)
|
||||
}
|
||||
ids[newRules[i].UID] = newRules[i].ID
|
||||
}
|
||||
}
|
||||
|
||||
if len(ruleVersions) > 0 {
|
||||
@ -179,15 +197,13 @@ func (st DBstore) InsertAlertRules(ctx context.Context, rules []ngmodels.AlertRu
|
||||
return fmt.Errorf("failed to create new rule versions: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateAlertRules is a handler for creating/updating alert rules.
|
||||
// UpdateAlertRules is a handler for updating alert rules.
|
||||
func (st DBstore) UpdateAlertRules(ctx context.Context, rules []UpdateRule) error {
|
||||
return st.SQLStore.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error {
|
||||
newRules := make([]ngmodels.AlertRule, 0, len(rules))
|
||||
ruleVersions := make([]ngmodels.AlertRuleVersion, 0, len(rules))
|
||||
for _, r := range rules {
|
||||
var parentVersion int64
|
||||
@ -226,14 +242,6 @@ func (st DBstore) UpdateAlertRules(ctx context.Context, rules []UpdateRule) erro
|
||||
Labels: r.New.Labels,
|
||||
})
|
||||
}
|
||||
if len(newRules) > 0 {
|
||||
if _, err := sess.Insert(&newRules); err != nil {
|
||||
if st.SQLStore.Dialect.IsUniqueConstraintViolation(err) {
|
||||
return ngmodels.ErrAlertRuleUniqueConstraintViolation
|
||||
}
|
||||
return fmt.Errorf("failed to create new rules: %w", err)
|
||||
}
|
||||
}
|
||||
if len(ruleVersions) > 0 {
|
||||
if _, err := sess.Insert(&ruleVersions); err != nil {
|
||||
return fmt.Errorf("failed to create new rule versions: %w", err)
|
||||
@ -296,6 +304,32 @@ func (st DBstore) GetRuleGroups(ctx context.Context, query *ngmodels.ListRuleGro
|
||||
})
|
||||
}
|
||||
|
||||
func (st DBstore) GetRuleGroupInterval(ctx context.Context, orgID int64, namespaceUID string, ruleGroup string) (int64, error) {
|
||||
var interval int64 = 0
|
||||
return interval, st.SQLStore.WithDbSession(ctx, func(sess *sqlstore.DBSession) error {
|
||||
ruleGroups := make([]ngmodels.AlertRule, 0)
|
||||
err := sess.Find(
|
||||
&ruleGroups,
|
||||
ngmodels.AlertRule{OrgID: orgID, RuleGroup: ruleGroup, NamespaceUID: namespaceUID},
|
||||
)
|
||||
if len(ruleGroups) == 0 {
|
||||
return ErrAlertRuleGroupNotFound
|
||||
}
|
||||
interval = ruleGroups[0].IntervalSeconds
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
||||
func (st DBstore) UpdateRuleGroup(ctx context.Context, orgID int64, namespaceUID string, ruleGroup string, interval int64) error {
|
||||
return st.SQLStore.WithDbSession(ctx, func(sess *sqlstore.DBSession) error {
|
||||
_, err := sess.Update(
|
||||
ngmodels.AlertRule{IntervalSeconds: interval},
|
||||
ngmodels.AlertRule{OrgID: orgID, RuleGroup: ruleGroup, NamespaceUID: namespaceUID},
|
||||
)
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
||||
// GetNamespaces returns the folders that are visible to the user and have at least one alert in it
|
||||
func (st DBstore) GetUserVisibleNamespaces(ctx context.Context, orgID int64, user *models.SignedInUser) (map[string]*models.Folder, error) {
|
||||
namespaceMap := make(map[string]*models.Folder)
|
||||
@ -433,5 +467,13 @@ func (st DBstore) validateAlertRule(alertRule ngmodels.AlertRule) error {
|
||||
return fmt.Errorf("%w: cannot have Panel ID without a Dashboard UID", ngmodels.ErrAlertRuleFailedValidation)
|
||||
}
|
||||
|
||||
if _, err := ngmodels.ErrStateFromString(string(alertRule.ExecErrState)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := ngmodels.NoDataStateFromString(string(alertRule.NoDataState)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -315,20 +315,43 @@ func (f *FakeRuleStore) UpdateAlertRules(_ context.Context, q []UpdateRule) erro
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *FakeRuleStore) InsertAlertRules(_ context.Context, q []models.AlertRule) error {
|
||||
func (f *FakeRuleStore) InsertAlertRules(_ context.Context, q []models.AlertRule) (map[string]int64, error) {
|
||||
f.mtx.Lock()
|
||||
defer f.mtx.Unlock()
|
||||
f.RecordedOps = append(f.RecordedOps, q)
|
||||
ids := make(map[string]int64, len(q))
|
||||
if err := f.Hook(q); err != nil {
|
||||
return err
|
||||
return ids, err
|
||||
}
|
||||
return nil
|
||||
return ids, nil
|
||||
}
|
||||
|
||||
func (f *FakeRuleStore) InTransaction(ctx context.Context, fn func(c context.Context) error) error {
|
||||
return fn(ctx)
|
||||
}
|
||||
|
||||
func (f *FakeRuleStore) GetRuleGroupInterval(ctx context.Context, orgID int64, namespaceUID string, ruleGroup string) (int64, error) {
|
||||
f.mtx.Lock()
|
||||
defer f.mtx.Unlock()
|
||||
for _, rule := range f.Rules[orgID] {
|
||||
if rule.RuleGroup == ruleGroup && rule.NamespaceUID == namespaceUID {
|
||||
return rule.IntervalSeconds, nil
|
||||
}
|
||||
}
|
||||
return 0, ErrAlertRuleGroupNotFound
|
||||
}
|
||||
|
||||
func (f *FakeRuleStore) UpdateRuleGroup(ctx context.Context, orgID int64, namespaceUID string, ruleGroup string, interval int64) error {
|
||||
f.mtx.Lock()
|
||||
defer f.mtx.Unlock()
|
||||
for _, rule := range f.Rules[orgID] {
|
||||
if rule.RuleGroup == ruleGroup && rule.NamespaceUID == namespaceUID {
|
||||
rule.IntervalSeconds = interval
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type FakeInstanceStore struct {
|
||||
mtx sync.Mutex
|
||||
RecordedOps []interface{}
|
||||
|
@ -84,7 +84,7 @@ func CreateTestAlertRule(t *testing.T, ctx context.Context, dbstore *store.DBsto
|
||||
|
||||
func CreateTestAlertRuleWithLabels(t *testing.T, ctx context.Context, dbstore *store.DBstore, intervalSeconds int64, orgID int64, labels map[string]string) *models.AlertRule {
|
||||
ruleGroup := fmt.Sprintf("ruleGroup-%s", util.GenerateShortUID())
|
||||
err := dbstore.InsertAlertRules(ctx, []models.AlertRule{
|
||||
_, err := dbstore.InsertAlertRules(ctx, []models.AlertRule{
|
||||
{
|
||||
|
||||
ID: 0,
|
||||
|
Loading…
Reference in New Issue
Block a user