diff --git a/pkg/services/ngalert/api/api_provisioning.go b/pkg/services/ngalert/api/api_provisioning.go index 27d349d220a..3a80c45dd45 100644 --- a/pkg/services/ngalert/api/api_provisioning.go +++ b/pkg/services/ngalert/api/api_provisioning.go @@ -54,6 +54,7 @@ type AlertRuleService interface { 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 + GetRuleGroup(ctx context.Context, orgID int64, folder, group string) (definitions.AlertRuleGroup, error) UpdateRuleGroup(ctx context.Context, orgID int64, folderUID, rulegroup string, interval int64) error } @@ -278,7 +279,18 @@ func (srv *ProvisioningSrv) RouteDeleteAlertRule(c *models.ReqContext, UID strin return response.JSON(http.StatusNoContent, "") } -func (srv *ProvisioningSrv) RoutePutAlertRuleGroup(c *models.ReqContext, ag definitions.AlertRuleGroup, folderUID string, group string) response.Response { +func (srv *ProvisioningSrv) RouteGetAlertRuleGroup(c *models.ReqContext, folder string, group string) response.Response { + g, err := srv.alertRules.GetRuleGroup(c.Req.Context(), c.OrgId, folder, group) + if err != nil { + if errors.Is(err, store.ErrAlertRuleGroupNotFound) { + return ErrResp(http.StatusNotFound, err, "") + } + return ErrResp(http.StatusInternalServerError, err, "") + } + return response.JSON(http.StatusOK, g) +} + +func (srv *ProvisioningSrv) RoutePutAlertRuleGroup(c *models.ReqContext, ag definitions.AlertRuleGroupMetadata, folderUID string, group string) response.Response { err := srv.alertRules.UpdateRuleGroup(c.Req.Context(), c.OrgId, folderUID, group, ag.Interval) if err != nil { return ErrResp(http.StatusInternalServerError, err, "") diff --git a/pkg/services/ngalert/api/api_provisioning_test.go b/pkg/services/ngalert/api/api_provisioning_test.go index 118dd0edb27..88574902f5f 100644 --- a/pkg/services/ngalert/api/api_provisioning_test.go +++ b/pkg/services/ngalert/api/api_provisioning_test.go @@ -239,6 +239,28 @@ func TestProvisioningApi(t *testing.T) { require.Equal(t, 404, response.Status()) }) }) + + t.Run("alert rule groups", func(t *testing.T) { + t.Run("are present, GET returns 200", func(t *testing.T) { + sut := createProvisioningSrvSut(t) + rc := createTestRequestCtx() + insertRule(t, sut, createTestAlertRule("rule", 1)) + + response := sut.RouteGetAlertRuleGroup(&rc, "folder-uid", "my-cool-group") + + require.Equal(t, 200, response.Status()) + }) + + t.Run("are missing, GET returns 404", func(t *testing.T) { + sut := createProvisioningSrvSut(t) + rc := createTestRequestCtx() + insertRule(t, sut, createTestAlertRule("rule", 1)) + + response := sut.RouteGetAlertRuleGroup(&rc, "folder-uid", "does not exist") + + require.Equal(t, 404, response.Status()) + }) + }) } func createProvisioningSrvSut(t *testing.T) ProvisioningSrv { @@ -382,6 +404,7 @@ func createTestAlertRule(title string, orgID int64) definitions.AlertRule { }, }, RuleGroup: "my-cool-group", + FolderUID: "folder-uid", For: time.Second * 60, NoDataState: models.OK, ExecErrState: models.OkErrState, diff --git a/pkg/services/ngalert/api/authorization.go b/pkg/services/ngalert/api/authorization.go index 231f6e7b507..713c718a077 100644 --- a/pkg/services/ngalert/api/authorization.go +++ b/pkg/services/ngalert/api/authorization.go @@ -185,7 +185,8 @@ func (api *API) authorize(method, path string) web.Handler { http.MethodGet + "/api/v1/provisioning/templates/{name}", http.MethodGet + "/api/v1/provisioning/mute-timings", http.MethodGet + "/api/v1/provisioning/mute-timings/{name}", - http.MethodGet + "/api/v1/provisioning/alert-rules/{UID}": + http.MethodGet + "/api/v1/provisioning/alert-rules/{UID}", + http.MethodGet + "/api/v1/provisioning/folder/{FolderUID}/rule-groups/{Group}": fallback = middleware.ReqOrgAdmin eval = ac.EvalPermission(ac.ActionAlertingProvisioningRead) // organization scope diff --git a/pkg/services/ngalert/api/forked_provisioning.go b/pkg/services/ngalert/api/forked_provisioning.go index 6446ef47bb5..3339ab10d1f 100644 --- a/pkg/services/ngalert/api/forked_provisioning.go +++ b/pkg/services/ngalert/api/forked_provisioning.go @@ -95,6 +95,10 @@ func (f *ForkedProvisioningApi) forkRouteDeleteAlertRule(ctx *models.ReqContext, return f.svc.RouteDeleteAlertRule(ctx, UID) } -func (f *ForkedProvisioningApi) forkRoutePutAlertRuleGroup(ctx *models.ReqContext, ag apimodels.AlertRuleGroup, folder, group string) response.Response { +func (f *ForkedProvisioningApi) forkRouteGetAlertRuleGroup(ctx *models.ReqContext, folder, group string) response.Response { + return f.svc.RouteGetAlertRuleGroup(ctx, folder, group) +} + +func (f *ForkedProvisioningApi) forkRoutePutAlertRuleGroup(ctx *models.ReqContext, ag apimodels.AlertRuleGroupMetadata, folder, group string) response.Response { return f.svc.RoutePutAlertRuleGroup(ctx, ag, folder, group) } diff --git a/pkg/services/ngalert/api/generated_base_api_provisioning.go b/pkg/services/ngalert/api/generated_base_api_provisioning.go index b449a168658..8fb66c89cc1 100644 --- a/pkg/services/ngalert/api/generated_base_api_provisioning.go +++ b/pkg/services/ngalert/api/generated_base_api_provisioning.go @@ -24,6 +24,7 @@ type ProvisioningApiForkingService interface { RouteDeleteMuteTiming(*models.ReqContext) response.Response RouteDeleteTemplate(*models.ReqContext) response.Response RouteGetAlertRule(*models.ReqContext) response.Response + RouteGetAlertRuleGroup(*models.ReqContext) response.Response RouteGetContactpoints(*models.ReqContext) response.Response RouteGetMuteTiming(*models.ReqContext) response.Response RouteGetMuteTimings(*models.ReqContext) response.Response @@ -61,6 +62,11 @@ func (f *ForkedProvisioningApi) RouteGetAlertRule(ctx *models.ReqContext) respon uIDParam := web.Params(ctx.Req)[":UID"] return f.forkRouteGetAlertRule(ctx, uIDParam) } +func (f *ForkedProvisioningApi) RouteGetAlertRuleGroup(ctx *models.ReqContext) response.Response { + folderUIDParam := web.Params(ctx.Req)[":FolderUID"] + groupParam := web.Params(ctx.Req)[":Group"] + return f.forkRouteGetAlertRuleGroup(ctx, folderUIDParam, groupParam) +} func (f *ForkedProvisioningApi) RouteGetContactpoints(ctx *models.ReqContext) response.Response { return f.forkRouteGetContactpoints(ctx) } @@ -113,7 +119,7 @@ func (f *ForkedProvisioningApi) RoutePutAlertRule(ctx *models.ReqContext) respon func (f *ForkedProvisioningApi) RoutePutAlertRuleGroup(ctx *models.ReqContext) response.Response { folderUIDParam := web.Params(ctx.Req)[":FolderUID"] groupParam := web.Params(ctx.Req)[":Group"] - conf := apimodels.AlertRuleGroup{} + conf := apimodels.AlertRuleGroupMetadata{} if err := web.Bind(ctx.Req, &conf); err != nil { return response.Error(http.StatusBadRequest, "bad request data", err) } @@ -203,6 +209,16 @@ func (api *API) RegisterProvisioningApiEndpoints(srv ProvisioningApiForkingServi m, ), ) + group.Get( + toMacaronPath("/api/v1/provisioning/folder/{FolderUID}/rule-groups/{Group}"), + api.authorize(http.MethodGet, "/api/v1/provisioning/folder/{FolderUID}/rule-groups/{Group}"), + metrics.Instrument( + http.MethodGet, + "/api/v1/provisioning/folder/{FolderUID}/rule-groups/{Group}", + srv.RouteGetAlertRuleGroup, + m, + ), + ) group.Get( toMacaronPath("/api/v1/provisioning/contact-points"), api.authorize(http.MethodGet, "/api/v1/provisioning/contact-points"), diff --git a/pkg/services/ngalert/api/tooling/api.json b/pkg/services/ngalert/api/tooling/api.json index a5ebb64a483..85932bbc80c 100644 --- a/pkg/services/ngalert/api/tooling/api.json +++ b/pkg/services/ngalert/api/tooling/api.json @@ -355,7 +355,7 @@ "type": "object", "x-go-package": "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions" }, - "AlertRuleGroup": { + "AlertRuleGroupMetadata": { "properties": { "interval": { "format": "int64", @@ -3373,6 +3373,7 @@ "x-go-package": "github.com/prometheus/alertmanager/api/v2/models" }, "alertGroup": { + "description": "AlertGroup alert group", "properties": { "alerts": { "description": "alerts", @@ -3394,17 +3395,14 @@ "labels", "receiver" ], - "type": "object", - "x-go-name": "AlertGroup", - "x-go-package": "github.com/prometheus/alertmanager/api/v2/models" + "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", @@ -3524,6 +3522,7 @@ "$ref": "#/definitions/Duration" }, "gettableAlert": { + "description": "GettableAlert gettable alert", "properties": { "annotations": { "$ref": "#/definitions/labelSet" @@ -3582,20 +3581,16 @@ "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", "items": { "$ref": "#/definitions/gettableAlert" }, - "type": "array", - "x-go-name": "GettableAlerts", - "x-go-package": "github.com/prometheus/alertmanager/api/v2/models" + "type": "array" }, "gettableSilence": { - "description": "GettableSilence gettable silence", "properties": { "comment": { "description": "comment", @@ -3647,7 +3642,9 @@ "status", "updatedAt" ], - "type": "object" + "type": "object", + "x-go-name": "GettableSilence", + "x-go-package": "github.com/prometheus/alertmanager/api/v2/models" }, "gettableSilences": { "description": "GettableSilences gettable silences", @@ -3783,6 +3780,7 @@ "x-go-package": "github.com/prometheus/alertmanager/api/v2/models" }, "postableSilence": { + "description": "PostableSilence postable silence", "properties": { "comment": { "description": "comment", @@ -3822,11 +3820,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", @@ -3837,9 +3834,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", @@ -4195,6 +4190,35 @@ } }, "/api/v1/provisioning/folder/{FolderUID}/rule-groups/{Group}": { + "get": { + "operationId": "RouteGetAlertRuleGroup", + "parameters": [ + { + "in": "path", + "name": "FolderUID", + "required": true, + "type": "string" + }, + { + "in": "path", + "name": "Group", + "required": true, + "type": "string" + } + ], + "responses": { + "200": { + "$ref": "#/responses/AlertRuleGroup" + }, + "404": { + "description": " Not found." + } + }, + "summary": "Get a rule group.", + "tags": [ + "provisioning" + ] + }, "put": { "consumes": [ "application/json" @@ -4217,15 +4241,15 @@ "in": "body", "name": "Body", "schema": { - "$ref": "#/definitions/AlertRuleGroup" + "$ref": "#/definitions/AlertRuleGroupMetadata" } } ], "responses": { "200": { - "description": "AlertRuleGroup", + "description": "AlertRuleGroupMetadata", "schema": { - "$ref": "#/definitions/AlertRuleGroup" + "$ref": "#/definitions/AlertRuleGroupMetadata" } }, "400": { diff --git a/pkg/services/ngalert/api/tooling/definitions/provisioning_alert_rules.go b/pkg/services/ngalert/api/tooling/definitions/provisioning_alert_rules.go index 44a7df7491e..d54f27090bd 100644 --- a/pkg/services/ngalert/api/tooling/definitions/provisioning_alert_rules.go +++ b/pkg/services/ngalert/api/tooling/definitions/provisioning_alert_rules.go @@ -135,6 +135,14 @@ func NewAlertRule(rule models.AlertRule, provenance models.Provenance) AlertRule } } +// swagger:route GET /api/v1/provisioning/folder/{FolderUID}/rule-groups/{Group} provisioning stable RouteGetAlertRuleGroup +// +// Get a rule group. +// +// Responses: +// 200: AlertRuleGroup +// 404: description: Not found. + // swagger:route PUT /api/v1/provisioning/folder/{FolderUID}/rule-groups/{Group} provisioning stable RoutePutAlertRuleGroup // // Update the interval of a rule group. @@ -143,16 +151,16 @@ func NewAlertRule(rule models.AlertRule, provenance models.Provenance) AlertRule // - application/json // // Responses: -// 200: AlertRuleGroup +// 200: AlertRuleGroupMetadata // 400: ValidationError -// swagger:parameters RoutePutAlertRuleGroup +// swagger:parameters RouteGetAlertRuleGroup RoutePutAlertRuleGroup type FolderUIDPathParam struct { // in:path FolderUID string `json:"FolderUID"` } -// swagger:parameters RoutePutAlertRuleGroup +// swagger:parameters RouteGetAlertRuleGroup RoutePutAlertRuleGroup type RuleGroupPathParam struct { // in:path Group string `json:"Group"` @@ -161,9 +169,16 @@ type RuleGroupPathParam struct { // swagger:parameters RoutePutAlertRuleGroup type AlertRuleGroupPayload struct { // in:body - Body AlertRuleGroup + Body AlertRuleGroupMetadata +} + +type AlertRuleGroupMetadata struct { + Interval int64 `json:"interval"` } type AlertRuleGroup struct { - Interval int64 `json:"interval"` + Title string `json:"title"` + FolderUID string `json:"folderUid"` + Interval int64 `json:"interval"` + Rules []models.AlertRule `json:"rules"` } diff --git a/pkg/services/ngalert/api/tooling/post.json b/pkg/services/ngalert/api/tooling/post.json index e15573d1d96..03b771229ac 100644 --- a/pkg/services/ngalert/api/tooling/post.json +++ b/pkg/services/ngalert/api/tooling/post.json @@ -355,7 +355,7 @@ "type": "object", "x-go-package": "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions" }, - "AlertRuleGroup": { + "AlertRuleGroupMetadata": { "properties": { "interval": { "format": "int64", @@ -3141,7 +3141,6 @@ "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" @@ -3174,9 +3173,9 @@ "$ref": "#/definitions/Userinfo" } }, - "title": "A URL represents a parsed URL (technically, a URI reference).", + "title": "URL is a custom URL type that allows validation at configuration load time.", "type": "object", - "x-go-package": "net/url" + "x-go-package": "github.com/prometheus/common/config" }, "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.", @@ -3374,6 +3373,7 @@ "x-go-package": "github.com/prometheus/alertmanager/api/v2/models" }, "alertGroup": { + "description": "AlertGroup alert group", "properties": { "alerts": { "description": "alerts", @@ -3395,16 +3395,15 @@ "labels", "receiver" ], - "type": "object", - "x-go-name": "AlertGroup", - "x-go-package": "github.com/prometheus/alertmanager/api/v2/models" + "type": "object" }, "alertGroups": { - "description": "AlertGroups alert groups", "items": { "$ref": "#/definitions/alertGroup" }, - "type": "array" + "type": "array", + "x-go-name": "AlertGroups", + "x-go-package": "github.com/prometheus/alertmanager/api/v2/models" }, "alertStatus": { "description": "AlertStatus alert status", @@ -3524,7 +3523,6 @@ "$ref": "#/definitions/Duration" }, "gettableAlert": { - "description": "GettableAlert gettable alert", "properties": { "annotations": { "$ref": "#/definitions/labelSet" @@ -3583,15 +3581,16 @@ "status", "updatedAt" ], - "type": "object" + "type": "object", + "x-go-name": "GettableAlert", + "x-go-package": "github.com/prometheus/alertmanager/api/v2/models" }, "gettableAlerts": { + "description": "GettableAlerts gettable alerts", "items": { "$ref": "#/definitions/gettableAlert" }, - "type": "array", - "x-go-name": "GettableAlerts", - "x-go-package": "github.com/prometheus/alertmanager/api/v2/models" + "type": "array" }, "gettableSilence": { "properties": { @@ -3650,11 +3649,12 @@ "x-go-package": "github.com/prometheus/alertmanager/api/v2/models" }, "gettableSilences": { - "description": "GettableSilences gettable silences", "items": { "$ref": "#/definitions/gettableSilence" }, - "type": "array" + "type": "array", + "x-go-name": "GettableSilences", + "x-go-package": "github.com/prometheus/alertmanager/api/v2/models" }, "labelSet": { "additionalProperties": { @@ -5784,7 +5784,7 @@ "operationId": "RouteDeleteContactpoints", "parameters": [ { - "description": "UID should be the contact point unique identifier", + "description": "UID is the contact point unique identifier", "in": "path", "name": "UID", "required": true, @@ -5808,7 +5808,7 @@ "operationId": "RoutePutContactpoint", "parameters": [ { - "description": "UID should be the contact point unique identifier", + "description": "UID is the contact point unique identifier", "in": "path", "name": "UID", "required": true, @@ -5843,6 +5843,35 @@ } }, "/api/v1/provisioning/folder/{FolderUID}/rule-groups/{Group}": { + "get": { + "operationId": "RouteGetAlertRuleGroup", + "parameters": [ + { + "in": "path", + "name": "FolderUID", + "required": true, + "type": "string" + }, + { + "in": "path", + "name": "Group", + "required": true, + "type": "string" + } + ], + "responses": { + "200": { + "$ref": "#/responses/AlertRuleGroup" + }, + "404": { + "description": " Not found." + } + }, + "summary": "Get a rule group.", + "tags": [ + "provisioning" + ] + }, "put": { "consumes": [ "application/json" @@ -5865,15 +5894,15 @@ "in": "body", "name": "Body", "schema": { - "$ref": "#/definitions/AlertRuleGroup" + "$ref": "#/definitions/AlertRuleGroupMetadata" } } ], "responses": { "200": { - "description": "AlertRuleGroup", + "description": "AlertRuleGroupMetadata", "schema": { - "$ref": "#/definitions/AlertRuleGroup" + "$ref": "#/definitions/AlertRuleGroupMetadata" } }, "400": { diff --git a/pkg/services/ngalert/api/tooling/spec.json b/pkg/services/ngalert/api/tooling/spec.json index 16e5c821136..fd53085e240 100644 --- a/pkg/services/ngalert/api/tooling/spec.json +++ b/pkg/services/ngalert/api/tooling/spec.json @@ -1862,7 +1862,7 @@ "parameters": [ { "type": "string", - "description": "UID should be the contact point unique identifier", + "description": "UID is the contact point unique identifier", "name": "UID", "in": "path", "required": true @@ -1903,7 +1903,7 @@ "parameters": [ { "type": "string", - "description": "UID should be the contact point unique identifier", + "description": "UID is the contact point unique identifier", "name": "UID", "in": "path", "required": true @@ -1917,6 +1917,36 @@ } }, "/api/v1/provisioning/folder/{FolderUID}/rule-groups/{Group}": { + "get": { + "tags": [ + "provisioning", + "stable" + ], + "summary": "Get a rule group.", + "operationId": "RouteGetAlertRuleGroup", + "parameters": [ + { + "type": "string", + "name": "FolderUID", + "in": "path", + "required": true + }, + { + "type": "string", + "name": "Group", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "$ref": "#/responses/AlertRuleGroup" + }, + "404": { + "description": " Not found." + } + } + }, "put": { "consumes": [ "application/json" @@ -1944,15 +1974,15 @@ "name": "Body", "in": "body", "schema": { - "$ref": "#/definitions/AlertRuleGroup" + "$ref": "#/definitions/AlertRuleGroupMetadata" } } ], "responses": { "200": { - "description": "AlertRuleGroup", + "description": "AlertRuleGroupMetadata", "schema": { - "$ref": "#/definitions/AlertRuleGroup" + "$ref": "#/definitions/AlertRuleGroupMetadata" } }, "400": { @@ -2706,7 +2736,7 @@ }, "x-go-package": "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions" }, - "AlertRuleGroup": { + "AlertRuleGroupMetadata": { "type": "object", "properties": { "interval": { @@ -5496,9 +5526,8 @@ "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": "A URL represents a parsed URL (technically, a URI reference).", + "title": "URL is a custom URL type that allows validation at configuration load time.", "properties": { "ForceQuery": { "type": "boolean" @@ -5531,7 +5560,7 @@ "$ref": "#/definitions/Userinfo" } }, - "x-go-package": "net/url" + "x-go-package": "github.com/prometheus/common/config" }, "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.", @@ -5729,6 +5758,7 @@ "x-go-package": "github.com/prometheus/alertmanager/api/v2/models" }, "alertGroup": { + "description": "AlertGroup alert group", "type": "object", "required": [ "alerts", @@ -5751,16 +5781,15 @@ "$ref": "#/definitions/receiver" } }, - "x-go-name": "AlertGroup", - "x-go-package": "github.com/prometheus/alertmanager/api/v2/models", "$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": { @@ -5881,7 +5910,6 @@ "$ref": "#/definitions/Duration" }, "gettableAlert": { - "description": "GettableAlert gettable alert", "type": "object", "required": [ "labels", @@ -5941,15 +5969,16 @@ "x-go-name": "UpdatedAt" } }, + "x-go-name": "GettableAlert", + "x-go-package": "github.com/prometheus/alertmanager/api/v2/models", "$ref": "#/definitions/gettableAlert" }, "gettableAlerts": { + "description": "GettableAlerts gettable alerts", "type": "array", "items": { "$ref": "#/definitions/gettableAlert" }, - "x-go-name": "GettableAlerts", - "x-go-package": "github.com/prometheus/alertmanager/api/v2/models", "$ref": "#/definitions/gettableAlerts" }, "gettableSilence": { @@ -6010,11 +6039,12 @@ "$ref": "#/definitions/gettableSilence" }, "gettableSilences": { - "description": "GettableSilences gettable silences", "type": "array", "items": { "$ref": "#/definitions/gettableSilence" }, + "x-go-name": "GettableSilences", + "x-go-package": "github.com/prometheus/alertmanager/api/v2/models", "$ref": "#/definitions/gettableSilences" }, "labelSet": { diff --git a/pkg/services/ngalert/provisioning/alert_rules.go b/pkg/services/ngalert/provisioning/alert_rules.go index 04e4e9a8987..5d618317eda 100644 --- a/pkg/services/ngalert/provisioning/alert_rules.go +++ b/pkg/services/ngalert/provisioning/alert_rules.go @@ -7,6 +7,7 @@ import ( "time" "github.com/grafana/grafana/pkg/infra/log" + "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/store" "github.com/grafana/grafana/pkg/util" @@ -89,6 +90,32 @@ func (service *AlertRuleService) CreateAlertRule(ctx context.Context, rule model return rule, nil } +func (service *AlertRuleService) GetRuleGroup(ctx context.Context, orgID int64, folder, group string) (definitions.AlertRuleGroup, error) { + q := models.ListAlertRulesQuery{ + OrgID: orgID, + NamespaceUIDs: []string{folder}, + RuleGroup: group, + } + if err := service.ruleStore.ListAlertRules(ctx, &q); err != nil { + return definitions.AlertRuleGroup{}, err + } + if len(q.Result) == 0 { + return definitions.AlertRuleGroup{}, store.ErrAlertRuleGroupNotFound + } + res := definitions.AlertRuleGroup{ + Title: q.Result[0].RuleGroup, + FolderUID: q.Result[0].NamespaceUID, + Interval: q.Result[0].IntervalSeconds, + Rules: []models.AlertRule{}, + } + for _, r := range q.Result { + if r != nil { + res.Rules = append(res.Rules, *r) + } + } + return res, nil +} + // UpdateRuleGroup will update the interval for all rules in the group. func (service *AlertRuleService) UpdateRuleGroup(ctx context.Context, orgID int64, namespaceUID string, ruleGroup string, interval int64) error { if err := models.ValidateRuleGroupInterval(interval, service.baseIntervalSeconds); err != nil {