Alerting: conversion API structure (#100258)

This commit is contained in:
Alexander Akhmetov 2025-02-12 08:13:21 +01:00 committed by GitHub
parent 9b37e9249a
commit 9593e51da7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 1333 additions and 8 deletions

View File

@ -253,6 +253,7 @@ export interface FeatureToggles {
exploreMetricsUseExternalAppPlugin?: boolean; exploreMetricsUseExternalAppPlugin?: boolean;
datasourceConnectionsTab?: boolean; datasourceConnectionsTab?: boolean;
fetchRulesUsingPost?: boolean; fetchRulesUsingPost?: boolean;
alertingConversionAPI?: boolean;
alertingAlertmanagerExtraDedupStage?: boolean; alertingAlertmanagerExtraDedupStage?: boolean;
alertingAlertmanagerExtraDedupStageStopPipeline?: boolean; alertingAlertmanagerExtraDedupStageStopPipeline?: boolean;
newLogsPanel?: boolean; newLogsPanel?: boolean;

View File

@ -1760,6 +1760,14 @@ var (
HideFromAdminPage: true, HideFromAdminPage: true,
HideFromDocs: true, HideFromDocs: true,
}, },
{
Name: "alertingConversionAPI",
Description: "Enable the alerting conversion API",
Stage: FeatureStageExperimental,
Owner: grafanaAlertingSquad,
HideFromAdminPage: true,
HideFromDocs: true,
},
{ {
Name: "alertingAlertmanagerExtraDedupStage", Name: "alertingAlertmanagerExtraDedupStage",
Description: "enables extra deduplication stage in alertmanager that checks that timestamps of the pipeline and the current state are matching", Description: "enables extra deduplication stage in alertmanager that checks that timestamps of the pipeline and the current state are matching",

View File

@ -234,6 +234,7 @@ elasticsearchImprovedParsing,experimental,@grafana/aws-datasources,false,false,f
exploreMetricsUseExternalAppPlugin,experimental,@grafana/observability-metrics,false,true,true exploreMetricsUseExternalAppPlugin,experimental,@grafana/observability-metrics,false,true,true
datasourceConnectionsTab,experimental,@grafana/plugins-platform-backend,false,false,true datasourceConnectionsTab,experimental,@grafana/plugins-platform-backend,false,false,true
fetchRulesUsingPost,experimental,@grafana/alerting-squad,false,false,false fetchRulesUsingPost,experimental,@grafana/alerting-squad,false,false,false
alertingConversionAPI,experimental,@grafana/alerting-squad,false,false,false
alertingAlertmanagerExtraDedupStage,experimental,@grafana/alerting-squad,false,true,false alertingAlertmanagerExtraDedupStage,experimental,@grafana/alerting-squad,false,true,false
alertingAlertmanagerExtraDedupStageStopPipeline,experimental,@grafana/alerting-squad,false,true,false alertingAlertmanagerExtraDedupStageStopPipeline,experimental,@grafana/alerting-squad,false,true,false
newLogsPanel,experimental,@grafana/observability-logs,false,false,true newLogsPanel,experimental,@grafana/observability-logs,false,false,true

1 Name Stage Owner requiresDevMode RequiresRestart FrontendOnly
234 exploreMetricsUseExternalAppPlugin experimental @grafana/observability-metrics false true true
235 datasourceConnectionsTab experimental @grafana/plugins-platform-backend false false true
236 fetchRulesUsingPost experimental @grafana/alerting-squad false false false
237 alertingConversionAPI experimental @grafana/alerting-squad false false false
238 alertingAlertmanagerExtraDedupStage experimental @grafana/alerting-squad false true false
239 alertingAlertmanagerExtraDedupStageStopPipeline experimental @grafana/alerting-squad false true false
240 newLogsPanel experimental @grafana/observability-logs false false true

View File

@ -947,6 +947,10 @@ const (
// Use a POST request to list rules by passing down the namespaces user has access to // Use a POST request to list rules by passing down the namespaces user has access to
FlagFetchRulesUsingPost = "fetchRulesUsingPost" FlagFetchRulesUsingPost = "fetchRulesUsingPost"
// FlagAlertingConversionAPI
// Enable the alerting conversion API
FlagAlertingConversionAPI = "alertingConversionAPI"
// FlagAlertingAlertmanagerExtraDedupStage // FlagAlertingAlertmanagerExtraDedupStage
// enables extra deduplication stage in alertmanager that checks that timestamps of the pipeline and the current state are matching // enables extra deduplication stage in alertmanager that checks that timestamps of the pipeline and the current state are matching
FlagAlertingAlertmanagerExtraDedupStage = "alertingAlertmanagerExtraDedupStage" FlagAlertingAlertmanagerExtraDedupStage = "alertingAlertmanagerExtraDedupStage"

View File

@ -215,6 +215,20 @@
"frontend": true "frontend": true
} }
}, },
{
"metadata": {
"name": "alertingConversionAPI",
"resourceVersion": "1739207762746",
"creationTimestamp": "2025-02-10T17:16:02Z"
},
"spec": {
"description": "Enable the alerting conversion API",
"stage": "experimental",
"codeowner": "@grafana/alerting-squad",
"hideFromAdminPage": true,
"hideFromDocs": true
}
},
{ {
"metadata": { "metadata": {
"name": "alertingDisableSendAlertsExternal", "name": "alertingDisableSendAlertsExternal",

View File

@ -185,4 +185,10 @@ func (api *API) RegisterAPIEndpoints(m *metrics.API) {
receiverService: api.ReceiverService, receiverService: api.ReceiverService,
muteTimingService: api.MuteTimings, muteTimingService: api.MuteTimings,
}), m) }), m)
if api.FeatureManager.IsEnabledGlobally(featuremgmt.FlagAlertingConversionAPI) {
api.RegisterConvertPrometheusApiEndpoints(NewConvertPrometheusApi(&ConvertPrometheusSrv{
logger: logger,
}), m)
}
} }

View File

@ -0,0 +1,36 @@
package api
import (
"github.com/grafana/grafana/pkg/api/response"
"github.com/grafana/grafana/pkg/infra/log"
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
apimodels "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
)
type ConvertPrometheusSrv struct {
logger log.Logger
}
func (srv *ConvertPrometheusSrv) RouteConvertPrometheusGetRules(c *contextmodel.ReqContext) response.Response {
return response.Error(501, "Not implemented", nil)
}
func (srv *ConvertPrometheusSrv) RouteConvertPrometheusDeleteNamespace(c *contextmodel.ReqContext, namespaceTitle string) response.Response {
return response.Error(501, "Not implemented", nil)
}
func (srv *ConvertPrometheusSrv) RouteConvertPrometheusDeleteRuleGroup(c *contextmodel.ReqContext, namespaceTitle string, group string) response.Response {
return response.Error(501, "Not implemented", nil)
}
func (srv *ConvertPrometheusSrv) RouteConvertPrometheusGetNamespace(c *contextmodel.ReqContext, namespaceTitle string) response.Response {
return response.Error(501, "Not implemented", nil)
}
func (srv *ConvertPrometheusSrv) RouteConvertPrometheusGetRuleGroup(c *contextmodel.ReqContext, namespaceTitle string, group string) response.Response {
return response.Error(501, "Not implemented", nil)
}
func (srv *ConvertPrometheusSrv) RouteConvertPrometheusPostRuleGroup(c *contextmodel.ReqContext, namespaceTitle string, prometheusGroup apimodels.PrometheusRuleGroup) response.Response {
return response.Error(501, "Not implemented", nil)
}

View File

@ -123,6 +123,34 @@ func (api *API) authorize(method, path string) web.Handler {
case http.MethodPost + "/api/v1/rule/test/{DatasourceUID}": case http.MethodPost + "/api/v1/rule/test/{DatasourceUID}":
eval = ac.EvalPermission(ac.ActionAlertingRuleExternalRead, datasources.ScopeProvider.GetResourceScopeUID(ac.Parameter(":DatasourceUID"))) eval = ac.EvalPermission(ac.ActionAlertingRuleExternalRead, datasources.ScopeProvider.GetResourceScopeUID(ac.Parameter(":DatasourceUID")))
// convert/prometheus API paths
case http.MethodGet + "/api/convert/prometheus/config/v1/rules/{NamespaceTitle}/{Group}",
http.MethodGet + "/api/convert/prometheus/config/v1/rules/{NamespaceTitle}":
eval = ac.EvalAll(
ac.EvalPermission(ac.ActionAlertingRuleRead),
ac.EvalPermission(dashboards.ActionFoldersRead),
)
case http.MethodGet + "/api/convert/prometheus/config/v1/rules":
eval = ac.EvalPermission(ac.ActionAlertingRuleRead)
case http.MethodPost + "/api/convert/prometheus/config/v1/rules/{NamespaceTitle}":
eval = ac.EvalAll(
ac.EvalPermission(dashboards.ActionFoldersWrite),
ac.EvalPermission(ac.ActionAlertingRuleRead),
ac.EvalPermission(ac.ActionAlertingRuleUpdate),
ac.EvalPermission(ac.ActionAlertingRuleCreate),
ac.EvalPermission(ac.ActionAlertingRuleDelete),
)
case http.MethodDelete + "/api/convert/prometheus/config/v1/rules/{NamespaceTitle}/{Group}",
http.MethodDelete + "/api/convert/prometheus/config/v1/rules/{NamespaceTitle}":
eval = ac.EvalAll(
ac.EvalPermission(ac.ActionAlertingRuleDelete),
ac.EvalPermission(ac.ActionAlertingRuleRead),
ac.EvalPermission(dashboards.ActionFoldersRead),
)
// Alert Instances and Silences // Alert Instances and Silences
// Silences for Grafana paths. // Silences for Grafana paths.

View File

@ -41,7 +41,7 @@ func TestAuthorize(t *testing.T) {
} }
paths[p] = methods paths[p] = methods
} }
require.Len(t, paths, 60) require.Len(t, paths, 63)
ac := acmock.New() ac := acmock.New()
api := &API{AccessControl: ac, FeatureManager: featuremgmt.WithFeatures()} api := &API{AccessControl: ac, FeatureManager: featuremgmt.WithFeatures()}

View File

@ -0,0 +1,136 @@
/*Package api contains base API implementation of unified alerting
*
*Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git)
*
*Do not manually edit these files, please find ngalert/api/swagger-codegen/ for commands on how to generate them.
*/
package api
import (
"net/http"
"github.com/grafana/grafana/pkg/api/response"
"github.com/grafana/grafana/pkg/api/routing"
"github.com/grafana/grafana/pkg/middleware"
"github.com/grafana/grafana/pkg/middleware/requestmeta"
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
"github.com/grafana/grafana/pkg/services/ngalert/metrics"
"github.com/grafana/grafana/pkg/web"
)
type ConvertPrometheusApi interface {
RouteConvertPrometheusDeleteNamespace(*contextmodel.ReqContext) response.Response
RouteConvertPrometheusDeleteRuleGroup(*contextmodel.ReqContext) response.Response
RouteConvertPrometheusGetNamespace(*contextmodel.ReqContext) response.Response
RouteConvertPrometheusGetRuleGroup(*contextmodel.ReqContext) response.Response
RouteConvertPrometheusGetRules(*contextmodel.ReqContext) response.Response
RouteConvertPrometheusPostRuleGroup(*contextmodel.ReqContext) response.Response
}
func (f *ConvertPrometheusApiHandler) RouteConvertPrometheusDeleteNamespace(ctx *contextmodel.ReqContext) response.Response {
// Parse Path Parameters
namespaceTitleParam := web.Params(ctx.Req)[":NamespaceTitle"]
return f.handleRouteConvertPrometheusDeleteNamespace(ctx, namespaceTitleParam)
}
func (f *ConvertPrometheusApiHandler) RouteConvertPrometheusDeleteRuleGroup(ctx *contextmodel.ReqContext) response.Response {
// Parse Path Parameters
namespaceTitleParam := web.Params(ctx.Req)[":NamespaceTitle"]
groupParam := web.Params(ctx.Req)[":Group"]
return f.handleRouteConvertPrometheusDeleteRuleGroup(ctx, namespaceTitleParam, groupParam)
}
func (f *ConvertPrometheusApiHandler) RouteConvertPrometheusGetNamespace(ctx *contextmodel.ReqContext) response.Response {
// Parse Path Parameters
namespaceTitleParam := web.Params(ctx.Req)[":NamespaceTitle"]
return f.handleRouteConvertPrometheusGetNamespace(ctx, namespaceTitleParam)
}
func (f *ConvertPrometheusApiHandler) RouteConvertPrometheusGetRuleGroup(ctx *contextmodel.ReqContext) response.Response {
// Parse Path Parameters
namespaceTitleParam := web.Params(ctx.Req)[":NamespaceTitle"]
groupParam := web.Params(ctx.Req)[":Group"]
return f.handleRouteConvertPrometheusGetRuleGroup(ctx, namespaceTitleParam, groupParam)
}
func (f *ConvertPrometheusApiHandler) RouteConvertPrometheusGetRules(ctx *contextmodel.ReqContext) response.Response {
return f.handleRouteConvertPrometheusGetRules(ctx)
}
func (f *ConvertPrometheusApiHandler) RouteConvertPrometheusPostRuleGroup(ctx *contextmodel.ReqContext) response.Response {
// Parse Path Parameters
namespaceTitleParam := web.Params(ctx.Req)[":NamespaceTitle"]
return f.handleRouteConvertPrometheusPostRuleGroup(ctx, namespaceTitleParam)
}
func (api *API) RegisterConvertPrometheusApiEndpoints(srv ConvertPrometheusApi, m *metrics.API) {
api.RouteRegister.Group("", func(group routing.RouteRegister) {
group.Delete(
toMacaronPath("/api/convert/prometheus/config/v1/rules/{NamespaceTitle}"),
requestmeta.SetOwner(requestmeta.TeamAlerting),
requestmeta.SetSLOGroup(requestmeta.SLOGroupHighSlow),
api.authorize(http.MethodDelete, "/api/convert/prometheus/config/v1/rules/{NamespaceTitle}"),
metrics.Instrument(
http.MethodDelete,
"/api/convert/prometheus/config/v1/rules/{NamespaceTitle}",
api.Hooks.Wrap(srv.RouteConvertPrometheusDeleteNamespace),
m,
),
)
group.Delete(
toMacaronPath("/api/convert/prometheus/config/v1/rules/{NamespaceTitle}/{Group}"),
requestmeta.SetOwner(requestmeta.TeamAlerting),
requestmeta.SetSLOGroup(requestmeta.SLOGroupHighSlow),
api.authorize(http.MethodDelete, "/api/convert/prometheus/config/v1/rules/{NamespaceTitle}/{Group}"),
metrics.Instrument(
http.MethodDelete,
"/api/convert/prometheus/config/v1/rules/{NamespaceTitle}/{Group}",
api.Hooks.Wrap(srv.RouteConvertPrometheusDeleteRuleGroup),
m,
),
)
group.Get(
toMacaronPath("/api/convert/prometheus/config/v1/rules/{NamespaceTitle}"),
requestmeta.SetOwner(requestmeta.TeamAlerting),
requestmeta.SetSLOGroup(requestmeta.SLOGroupHighSlow),
api.authorize(http.MethodGet, "/api/convert/prometheus/config/v1/rules/{NamespaceTitle}"),
metrics.Instrument(
http.MethodGet,
"/api/convert/prometheus/config/v1/rules/{NamespaceTitle}",
api.Hooks.Wrap(srv.RouteConvertPrometheusGetNamespace),
m,
),
)
group.Get(
toMacaronPath("/api/convert/prometheus/config/v1/rules/{NamespaceTitle}/{Group}"),
requestmeta.SetOwner(requestmeta.TeamAlerting),
requestmeta.SetSLOGroup(requestmeta.SLOGroupHighSlow),
api.authorize(http.MethodGet, "/api/convert/prometheus/config/v1/rules/{NamespaceTitle}/{Group}"),
metrics.Instrument(
http.MethodGet,
"/api/convert/prometheus/config/v1/rules/{NamespaceTitle}/{Group}",
api.Hooks.Wrap(srv.RouteConvertPrometheusGetRuleGroup),
m,
),
)
group.Get(
toMacaronPath("/api/convert/prometheus/config/v1/rules"),
requestmeta.SetOwner(requestmeta.TeamAlerting),
requestmeta.SetSLOGroup(requestmeta.SLOGroupHighSlow),
api.authorize(http.MethodGet, "/api/convert/prometheus/config/v1/rules"),
metrics.Instrument(
http.MethodGet,
"/api/convert/prometheus/config/v1/rules",
api.Hooks.Wrap(srv.RouteConvertPrometheusGetRules),
m,
),
)
group.Post(
toMacaronPath("/api/convert/prometheus/config/v1/rules/{NamespaceTitle}"),
requestmeta.SetOwner(requestmeta.TeamAlerting),
requestmeta.SetSLOGroup(requestmeta.SLOGroupHighSlow),
api.authorize(http.MethodPost, "/api/convert/prometheus/config/v1/rules/{NamespaceTitle}"),
metrics.Instrument(
http.MethodPost,
"/api/convert/prometheus/config/v1/rules/{NamespaceTitle}",
api.Hooks.Wrap(srv.RouteConvertPrometheusPostRuleGroup),
m,
),
)
}, middleware.ReqSignedIn)
}

View File

@ -0,0 +1,56 @@
package api
import (
"io"
"gopkg.in/yaml.v3"
"github.com/grafana/grafana/pkg/api/response"
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
apimodels "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
)
type ConvertPrometheusApiHandler struct {
svc *ConvertPrometheusSrv
}
func NewConvertPrometheusApi(svc *ConvertPrometheusSrv) *ConvertPrometheusApiHandler {
return &ConvertPrometheusApiHandler{
svc: svc,
}
}
func (f *ConvertPrometheusApiHandler) handleRouteConvertPrometheusGetRules(ctx *contextmodel.ReqContext) response.Response {
return f.svc.RouteConvertPrometheusGetRules(ctx)
}
func (f *ConvertPrometheusApiHandler) handleRouteConvertPrometheusDeleteNamespace(ctx *contextmodel.ReqContext, namespaceTitle string) response.Response {
return f.svc.RouteConvertPrometheusDeleteNamespace(ctx, namespaceTitle)
}
func (f *ConvertPrometheusApiHandler) handleRouteConvertPrometheusDeleteRuleGroup(ctx *contextmodel.ReqContext, namespaceTitle string, group string) response.Response {
return f.svc.RouteConvertPrometheusDeleteRuleGroup(ctx, namespaceTitle, group)
}
func (f *ConvertPrometheusApiHandler) handleRouteConvertPrometheusGetNamespace(ctx *contextmodel.ReqContext, namespaceTitle string) response.Response {
return f.svc.RouteConvertPrometheusGetNamespace(ctx, namespaceTitle)
}
func (f *ConvertPrometheusApiHandler) handleRouteConvertPrometheusGetRuleGroup(ctx *contextmodel.ReqContext, namespaceTitle string, group string) response.Response {
return f.svc.RouteConvertPrometheusGetRuleGroup(ctx, namespaceTitle, group)
}
func (f *ConvertPrometheusApiHandler) handleRouteConvertPrometheusPostRuleGroup(ctx *contextmodel.ReqContext, namespaceTitle string) response.Response {
body, err := io.ReadAll(ctx.Req.Body)
if err != nil {
return errorToResponse(err)
}
defer func() { _ = ctx.Req.Body.Close() }()
var promGroup apimodels.PrometheusRuleGroup
if err := yaml.Unmarshal(body, &promGroup); err != nil {
return errorToResponse(err)
}
return f.svc.RouteConvertPrometheusPostRuleGroup(ctx, namespaceTitle, promGroup)
}

View File

@ -734,6 +734,20 @@
}, },
"type": "array" "type": "array"
}, },
"ConvertPrometheusResponse": {
"properties": {
"error": {
"type": "string"
},
"errorType": {
"type": "string"
},
"status": {
"type": "string"
}
},
"type": "object"
},
"CounterResetHint": { "CounterResetHint": {
"description": "or alternatively that we are dealing with a gauge histogram, where counter resets do not apply.", "description": "or alternatively that we are dealing with a gauge histogram, where counter resets do not apply.",
"format": "uint8", "format": "uint8",
@ -2940,6 +2954,70 @@
}, },
"type": "object" "type": "object"
}, },
"PrometheusNamespace": {
"properties": {
"Body": {
"additionalProperties": {
"items": {
"$ref": "#/definitions/PrometheusRuleGroup"
},
"type": "array"
},
"description": "in: body",
"type": "object"
}
},
"type": "object"
},
"PrometheusRule": {
"properties": {
"Alert": {
"type": "string"
},
"Annotations": {
"additionalProperties": {
"type": "string"
},
"type": "object"
},
"Expr": {
"type": "string"
},
"For": {
"type": "string"
},
"KeepFiringFor": {
"type": "string"
},
"Labels": {
"additionalProperties": {
"type": "string"
},
"type": "object"
},
"Record": {
"type": "string"
}
},
"type": "object"
},
"PrometheusRuleGroup": {
"properties": {
"Interval": {
"$ref": "#/definitions/Duration"
},
"Name": {
"type": "string"
},
"Rules": {
"items": {
"$ref": "#/definitions/PrometheusRule"
},
"type": "array"
}
},
"type": "object"
},
"Provenance": { "Provenance": {
"type": "string" "type": "string"
}, },
@ -4692,7 +4770,6 @@
"type": "object" "type": "object"
}, },
"alertGroups": { "alertGroups": {
"description": "AlertGroups alert groups",
"items": { "items": {
"$ref": "#/definitions/alertGroup", "$ref": "#/definitions/alertGroup",
"type": "object" "type": "object"

View File

@ -0,0 +1,139 @@
package definitions
import (
"github.com/prometheus/common/model"
)
// swagger:route GET /convert/prometheus/config/v1/rules convert_prometheus RouteConvertPrometheusGetRules
//
// Gets all namespaces with their rule groups in Prometheus format.
//
// Produces:
// - application/json
//
// Responses:
// 200: PrometheusNamespace
// 403: ForbiddenError
// 404: NotFound
// swagger:route GET /convert/prometheus/config/v1/rules/{NamespaceTitle} convert_prometheus RouteConvertPrometheusGetNamespace
//
// Gets rules in prometheus format for a given namespace.
//
// Produces:
// - application/json
//
// Responses:
// 200: PrometheusNamespace
// 403: ForbiddenError
// 404: NotFound
// swagger:route GET /convert/prometheus/config/v1/rules/{NamespaceTitle}/{Group} convert_prometheus RouteConvertPrometheusGetRuleGroup
//
// Gets a rule group in Prometheus format.
//
// Produces:
// - application/json
//
// Responses:
// 200: PrometheusRuleGroup
// 403: ForbiddenError
// 404: NotFound
// swagger:route POST /convert/prometheus/config/v1/rules/{NamespaceTitle} convert_prometheus RouteConvertPrometheusPostRuleGroup
//
// Creates or updates a rule group in Prometheus format.
//
// Consumes:
// - application/yaml
//
// Produces:
// - application/json
//
// Responses:
// 202: ConvertPrometheusResponse
// 403: ForbiddenError
//
// Extensions:
// x-raw-request: true
// swagger:route DELETE /convert/prometheus/config/v1/rules/{NamespaceTitle} convert_prometheus RouteConvertPrometheusDeleteNamespace
//
// Deletes all rule groups in the given namespace.
//
// Produces:
// - application/json
//
// Responses:
// 202: ConvertPrometheusResponse
// 403: ForbiddenError
// swagger:route DELETE /convert/prometheus/config/v1/rules/{NamespaceTitle}/{Group} convert_prometheus RouteConvertPrometheusDeleteRuleGroup
//
// Deletes a rule group in Prometheus format.
//
// Produces:
// - application/json
//
// Responses:
// 202: ConvertPrometheusResponse
// 403: ForbiddenError
// swagger:parameters RouteConvertPrometheusPostRuleGroup
type RouteConvertPrometheusPostRuleGroupParams struct {
// in: path
NamespaceTitle string
// in: header
DatasourceUID string `json:"x-datasource-uid"`
// in: header
RecordingRulesPaused bool `json:"x-recording-rules-paused"`
// in: header
AlertRulesPaused bool `json:"x-alert-rules-paused"`
// in:body
Body PrometheusRuleGroup
}
// swagger:model
type PrometheusNamespace struct {
// in: body
Body map[string][]PrometheusRuleGroup
}
// swagger:model
type PrometheusRuleGroup struct {
Name string `yaml:"name"`
Interval model.Duration `yaml:"interval"`
Rules []PrometheusRule `yaml:"rules"`
}
// swagger:model
type PrometheusRule struct {
Alert string `yaml:"alert,omitempty"`
Expr string `yaml:"expr"`
For *model.Duration `yaml:"for,omitempty"`
KeepFiringFor *model.Duration `yaml:"keep_firing_for,omitempty"`
Labels map[string]string `yaml:"labels,omitempty"`
Annotations map[string]string `yaml:"annotations,omitempty"`
Record string `yaml:"record,omitempty"`
}
// swagger:parameters RouteConvertPrometheusDeleteRuleGroup RouteConvertPrometheusGetRuleGroup
type RouteConvertPrometheusDeleteRuleGroupParams struct {
// in: path
NamespaceTitle string
// in: path
Group string
}
// swagger:parameters RouteConvertPrometheusDeleteNamespace RouteConvertPrometheusGetNamespace
type RouteConvertPrometheusDeleteNamespaceParams struct {
// in: path
NamespaceTitle string
}
// swagger:model
type ConvertPrometheusResponse struct {
Status string `json:"status"`
ErrorType string `json:"errorType"`
Error string `json:"error"`
}

View File

@ -734,6 +734,20 @@
}, },
"type": "array" "type": "array"
}, },
"ConvertPrometheusResponse": {
"properties": {
"error": {
"type": "string"
},
"errorType": {
"type": "string"
},
"status": {
"type": "string"
}
},
"type": "object"
},
"CounterResetHint": { "CounterResetHint": {
"description": "or alternatively that we are dealing with a gauge histogram, where counter resets do not apply.", "description": "or alternatively that we are dealing with a gauge histogram, where counter resets do not apply.",
"format": "uint8", "format": "uint8",
@ -2940,6 +2954,70 @@
}, },
"type": "object" "type": "object"
}, },
"PrometheusNamespace": {
"properties": {
"Body": {
"additionalProperties": {
"items": {
"$ref": "#/definitions/PrometheusRuleGroup"
},
"type": "array"
},
"description": "in: body",
"type": "object"
}
},
"type": "object"
},
"PrometheusRule": {
"properties": {
"Alert": {
"type": "string"
},
"Annotations": {
"additionalProperties": {
"type": "string"
},
"type": "object"
},
"Expr": {
"type": "string"
},
"For": {
"type": "string"
},
"KeepFiringFor": {
"type": "string"
},
"Labels": {
"additionalProperties": {
"type": "string"
},
"type": "object"
},
"Record": {
"type": "string"
}
},
"type": "object"
},
"PrometheusRuleGroup": {
"properties": {
"Interval": {
"$ref": "#/definitions/Duration"
},
"Name": {
"type": "string"
},
"Rules": {
"items": {
"$ref": "#/definitions/PrometheusRule"
},
"type": "array"
}
},
"type": "object"
},
"Provenance": { "Provenance": {
"type": "string" "type": "string"
}, },
@ -4854,7 +4932,6 @@
"type": "object" "type": "object"
}, },
"gettableAlerts": { "gettableAlerts": {
"description": "GettableAlerts gettable alerts",
"items": { "items": {
"$ref": "#/definitions/gettableAlert", "$ref": "#/definitions/gettableAlert",
"type": "object" "type": "object"
@ -4979,7 +5056,6 @@
"type": "object" "type": "object"
}, },
"gettableSilences": { "gettableSilences": {
"description": "GettableSilences gettable silences",
"items": { "items": {
"$ref": "#/definitions/gettableSilence", "$ref": "#/definitions/gettableSilence",
"type": "object" "type": "object"
@ -6322,6 +6398,252 @@
] ]
} }
}, },
"/convert/prometheus/config/v1/rules": {
"get": {
"operationId": "RouteConvertPrometheusGetRules",
"produces": [
"application/json"
],
"responses": {
"200": {
"description": "PrometheusNamespace",
"schema": {
"$ref": "#/definitions/PrometheusNamespace"
}
},
"403": {
"description": "ForbiddenError",
"schema": {
"$ref": "#/definitions/ForbiddenError"
}
},
"404": {
"description": "NotFound",
"schema": {
"$ref": "#/definitions/NotFound"
}
}
},
"summary": "Gets all namespaces with their rule groups in Prometheus format.",
"tags": [
"convert_prometheus"
]
}
},
"/convert/prometheus/config/v1/rules/{NamespaceTitle}": {
"delete": {
"operationId": "RouteConvertPrometheusDeleteNamespace",
"parameters": [
{
"in": "path",
"name": "NamespaceTitle",
"required": true,
"type": "string"
}
],
"produces": [
"application/json"
],
"responses": {
"202": {
"description": "ConvertPrometheusResponse",
"schema": {
"$ref": "#/definitions/ConvertPrometheusResponse"
}
},
"403": {
"description": "ForbiddenError",
"schema": {
"$ref": "#/definitions/ForbiddenError"
}
}
},
"summary": "Deletes all rule groups in the given namespace.",
"tags": [
"convert_prometheus"
]
},
"get": {
"operationId": "RouteConvertPrometheusGetNamespace",
"parameters": [
{
"in": "path",
"name": "NamespaceTitle",
"required": true,
"type": "string"
}
],
"produces": [
"application/json"
],
"responses": {
"200": {
"description": "PrometheusNamespace",
"schema": {
"$ref": "#/definitions/PrometheusNamespace"
}
},
"403": {
"description": "ForbiddenError",
"schema": {
"$ref": "#/definitions/ForbiddenError"
}
},
"404": {
"description": "NotFound",
"schema": {
"$ref": "#/definitions/NotFound"
}
}
},
"summary": "Gets rules in prometheus format for a given namespace.",
"tags": [
"convert_prometheus"
]
},
"post": {
"consumes": [
"application/yaml"
],
"operationId": "RouteConvertPrometheusPostRuleGroup",
"parameters": [
{
"in": "path",
"name": "NamespaceTitle",
"required": true,
"type": "string"
},
{
"in": "header",
"name": "x-datasource-uid",
"type": "string"
},
{
"in": "header",
"name": "x-recording-rules-paused",
"type": "boolean"
},
{
"in": "header",
"name": "x-alert-rules-paused",
"type": "boolean"
},
{
"in": "body",
"name": "Body",
"schema": {
"$ref": "#/definitions/PrometheusRuleGroup"
}
}
],
"produces": [
"application/json"
],
"responses": {
"202": {
"description": "ConvertPrometheusResponse",
"schema": {
"$ref": "#/definitions/ConvertPrometheusResponse"
}
},
"403": {
"description": "ForbiddenError",
"schema": {
"$ref": "#/definitions/ForbiddenError"
}
}
},
"summary": "Creates or updates a rule group in Prometheus format.",
"tags": [
"convert_prometheus"
],
"x-raw-request": "true"
}
},
"/convert/prometheus/config/v1/rules/{NamespaceTitle}/{Group}": {
"delete": {
"operationId": "RouteConvertPrometheusDeleteRuleGroup",
"parameters": [
{
"in": "path",
"name": "NamespaceTitle",
"required": true,
"type": "string"
},
{
"in": "path",
"name": "Group",
"required": true,
"type": "string"
}
],
"produces": [
"application/json"
],
"responses": {
"202": {
"description": "ConvertPrometheusResponse",
"schema": {
"$ref": "#/definitions/ConvertPrometheusResponse"
}
},
"403": {
"description": "ForbiddenError",
"schema": {
"$ref": "#/definitions/ForbiddenError"
}
}
},
"summary": "Deletes a rule group in Prometheus format.",
"tags": [
"convert_prometheus"
]
},
"get": {
"operationId": "RouteConvertPrometheusGetRuleGroup",
"parameters": [
{
"in": "path",
"name": "NamespaceTitle",
"required": true,
"type": "string"
},
{
"in": "path",
"name": "Group",
"required": true,
"type": "string"
}
],
"produces": [
"application/json"
],
"responses": {
"200": {
"description": "PrometheusRuleGroup",
"schema": {
"$ref": "#/definitions/PrometheusRuleGroup"
}
},
"403": {
"description": "ForbiddenError",
"schema": {
"$ref": "#/definitions/ForbiddenError"
}
},
"404": {
"description": "NotFound",
"schema": {
"$ref": "#/definitions/NotFound"
}
}
},
"summary": "Gets a rule group in Prometheus format.",
"tags": [
"convert_prometheus"
]
}
},
"/prometheus/grafana/api/v1/alerts": { "/prometheus/grafana/api/v1/alerts": {
"get": { "get": {
"description": "gets the current alerts", "description": "gets the current alerts",
@ -6886,6 +7208,12 @@
"schema": { "schema": {
"$ref": "#/definitions/ForbiddenError" "$ref": "#/definitions/ForbiddenError"
} }
},
"404": {
"description": "NotFound",
"schema": {
"$ref": "#/definitions/NotFound"
}
} }
}, },
"tags": [ "tags": [

View File

@ -1102,6 +1102,252 @@
} }
} }
}, },
"/convert/prometheus/config/v1/rules": {
"get": {
"produces": [
"application/json"
],
"tags": [
"convert_prometheus"
],
"summary": "Gets all namespaces with their rule groups in Prometheus format.",
"operationId": "RouteConvertPrometheusGetRules",
"responses": {
"200": {
"description": "PrometheusNamespace",
"schema": {
"$ref": "#/definitions/PrometheusNamespace"
}
},
"403": {
"description": "ForbiddenError",
"schema": {
"$ref": "#/definitions/ForbiddenError"
}
},
"404": {
"description": "NotFound",
"schema": {
"$ref": "#/definitions/NotFound"
}
}
}
}
},
"/convert/prometheus/config/v1/rules/{NamespaceTitle}": {
"get": {
"produces": [
"application/json"
],
"tags": [
"convert_prometheus"
],
"summary": "Gets rules in prometheus format for a given namespace.",
"operationId": "RouteConvertPrometheusGetNamespace",
"parameters": [
{
"type": "string",
"name": "NamespaceTitle",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "PrometheusNamespace",
"schema": {
"$ref": "#/definitions/PrometheusNamespace"
}
},
"403": {
"description": "ForbiddenError",
"schema": {
"$ref": "#/definitions/ForbiddenError"
}
},
"404": {
"description": "NotFound",
"schema": {
"$ref": "#/definitions/NotFound"
}
}
}
},
"post": {
"consumes": [
"application/yaml"
],
"produces": [
"application/json"
],
"tags": [
"convert_prometheus"
],
"summary": "Creates or updates a rule group in Prometheus format.",
"operationId": "RouteConvertPrometheusPostRuleGroup",
"parameters": [
{
"type": "string",
"name": "NamespaceTitle",
"in": "path",
"required": true
},
{
"type": "string",
"name": "x-datasource-uid",
"in": "header"
},
{
"type": "boolean",
"name": "x-recording-rules-paused",
"in": "header"
},
{
"type": "boolean",
"name": "x-alert-rules-paused",
"in": "header"
},
{
"name": "Body",
"in": "body",
"schema": {
"$ref": "#/definitions/PrometheusRuleGroup"
}
}
],
"responses": {
"202": {
"description": "ConvertPrometheusResponse",
"schema": {
"$ref": "#/definitions/ConvertPrometheusResponse"
}
},
"403": {
"description": "ForbiddenError",
"schema": {
"$ref": "#/definitions/ForbiddenError"
}
}
},
"x-raw-request": "true"
},
"delete": {
"produces": [
"application/json"
],
"tags": [
"convert_prometheus"
],
"summary": "Deletes all rule groups in the given namespace.",
"operationId": "RouteConvertPrometheusDeleteNamespace",
"parameters": [
{
"type": "string",
"name": "NamespaceTitle",
"in": "path",
"required": true
}
],
"responses": {
"202": {
"description": "ConvertPrometheusResponse",
"schema": {
"$ref": "#/definitions/ConvertPrometheusResponse"
}
},
"403": {
"description": "ForbiddenError",
"schema": {
"$ref": "#/definitions/ForbiddenError"
}
}
}
}
},
"/convert/prometheus/config/v1/rules/{NamespaceTitle}/{Group}": {
"get": {
"produces": [
"application/json"
],
"tags": [
"convert_prometheus"
],
"summary": "Gets a rule group in Prometheus format.",
"operationId": "RouteConvertPrometheusGetRuleGroup",
"parameters": [
{
"type": "string",
"name": "NamespaceTitle",
"in": "path",
"required": true
},
{
"type": "string",
"name": "Group",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "PrometheusRuleGroup",
"schema": {
"$ref": "#/definitions/PrometheusRuleGroup"
}
},
"403": {
"description": "ForbiddenError",
"schema": {
"$ref": "#/definitions/ForbiddenError"
}
},
"404": {
"description": "NotFound",
"schema": {
"$ref": "#/definitions/NotFound"
}
}
}
},
"delete": {
"produces": [
"application/json"
],
"tags": [
"convert_prometheus"
],
"summary": "Deletes a rule group in Prometheus format.",
"operationId": "RouteConvertPrometheusDeleteRuleGroup",
"parameters": [
{
"type": "string",
"name": "NamespaceTitle",
"in": "path",
"required": true
},
{
"type": "string",
"name": "Group",
"in": "path",
"required": true
}
],
"responses": {
"202": {
"description": "ConvertPrometheusResponse",
"schema": {
"$ref": "#/definitions/ConvertPrometheusResponse"
}
},
"403": {
"description": "ForbiddenError",
"schema": {
"$ref": "#/definitions/ForbiddenError"
}
}
}
}
},
"/prometheus/grafana/api/v1/alerts": { "/prometheus/grafana/api/v1/alerts": {
"get": { "get": {
"description": "gets the current alerts", "description": "gets the current alerts",
@ -1633,6 +1879,12 @@
"schema": { "schema": {
"$ref": "#/definitions/ForbiddenError" "$ref": "#/definitions/ForbiddenError"
} }
},
"404": {
"description": "NotFound",
"schema": {
"$ref": "#/definitions/NotFound"
}
} }
} }
}, },
@ -4420,6 +4672,20 @@
"$ref": "#/definitions/EmbeddedContactPoint" "$ref": "#/definitions/EmbeddedContactPoint"
} }
}, },
"ConvertPrometheusResponse": {
"type": "object",
"properties": {
"error": {
"type": "string"
},
"errorType": {
"type": "string"
},
"status": {
"type": "string"
}
}
},
"CounterResetHint": { "CounterResetHint": {
"description": "or alternatively that we are dealing with a gauge histogram, where counter resets do not apply.", "description": "or alternatively that we are dealing with a gauge histogram, where counter resets do not apply.",
"type": "integer", "type": "integer",
@ -6628,6 +6894,70 @@
} }
} }
}, },
"PrometheusNamespace": {
"type": "object",
"properties": {
"Body": {
"description": "in: body",
"type": "object",
"additionalProperties": {
"type": "array",
"items": {
"$ref": "#/definitions/PrometheusRuleGroup"
}
}
}
}
},
"PrometheusRule": {
"type": "object",
"properties": {
"Alert": {
"type": "string"
},
"Annotations": {
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"Expr": {
"type": "string"
},
"For": {
"type": "string"
},
"KeepFiringFor": {
"type": "string"
},
"Labels": {
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"Record": {
"type": "string"
}
}
},
"PrometheusRuleGroup": {
"type": "object",
"properties": {
"Interval": {
"$ref": "#/definitions/Duration"
},
"Name": {
"type": "string"
},
"Rules": {
"type": "array",
"items": {
"$ref": "#/definitions/PrometheusRule"
}
}
}
},
"Provenance": { "Provenance": {
"type": "string" "type": "string"
}, },
@ -8542,7 +8872,6 @@
} }
}, },
"gettableAlerts": { "gettableAlerts": {
"description": "GettableAlerts gettable alerts",
"type": "array", "type": "array",
"items": { "items": {
"type": "object", "type": "object",
@ -8667,7 +8996,6 @@
} }
}, },
"gettableSilences": { "gettableSilences": {
"description": "GettableSilences gettable silences",
"type": "array", "type": "array",
"items": { "items": {
"type": "object", "type": "object",

View File

@ -20,6 +20,14 @@ type {{classname}} interface { {{#operation}}
} }
{{#operations}}{{#operation}} {{#operations}}{{#operation}}
{{#vendorExtensions.x-raw-request}}
func (f *{{classname}}Handler) {{nickname}}(ctx *contextmodel.ReqContext) response.Response { {{#hasPathParams}}
// Parse Path Parameters{{/hasPathParams}}{{#pathParams}}
{{paramName}}Param := web.Params(ctx.Req)[":{{baseName}}"]{{/pathParams}}
return f.handle{{nickname}}(ctx{{#pathParams}}, {{paramName}}Param{{/pathParams}})
}
{{/vendorExtensions.x-raw-request}}
{{^vendorExtensions.x-raw-request}}
func (f *{{classname}}Handler) {{nickname}}(ctx *contextmodel.ReqContext) response.Response { {{#hasPathParams}} func (f *{{classname}}Handler) {{nickname}}(ctx *contextmodel.ReqContext) response.Response { {{#hasPathParams}}
// Parse Path Parameters{{/hasPathParams}}{{#pathParams}} // Parse Path Parameters{{/hasPathParams}}{{#pathParams}}
{{paramName}}Param := web.Params(ctx.Req)[":{{baseName}}"]{{/pathParams}} {{paramName}}Param := web.Params(ctx.Req)[":{{baseName}}"]{{/pathParams}}
@ -31,6 +39,7 @@ func (f *{{classname}}Handler) {{nickname}}(ctx *contextmodel.ReqContext) respon
} }
{{/bodyParams}}return f.handle{{nickname}}(ctx{{#bodyParams}}, conf{{/bodyParams}}{{#pathParams}}, {{paramName}}Param{{/pathParams}}) {{/bodyParams}}return f.handle{{nickname}}(ctx{{#bodyParams}}, conf{{/bodyParams}}{{#pathParams}}, {{paramName}}Param{{/pathParams}})
} }
{{/vendorExtensions.x-raw-request}}
{{/operation}}{{/operations}} {{/operation}}{{/operations}}
func (api *API) Register{{classname}}Endpoints(srv {{classname}}, m *metrics.API) { func (api *API) Register{{classname}}Endpoints(srv {{classname}}, m *metrics.API) {

View File

@ -13882,6 +13882,20 @@
"$ref": "#/definitions/EmbeddedContactPoint" "$ref": "#/definitions/EmbeddedContactPoint"
} }
}, },
"ConvertPrometheusResponse": {
"type": "object",
"properties": {
"error": {
"type": "string"
},
"errorType": {
"type": "string"
},
"status": {
"type": "string"
}
}
},
"CookiePreferences": { "CookiePreferences": {
"type": "object", "type": "object",
"properties": { "properties": {
@ -18520,6 +18534,21 @@
} }
} }
}, },
"PrometheusNamespace": {
"type": "object",
"properties": {
"Body": {
"description": "in: body",
"type": "object",
"additionalProperties": {
"type": "array",
"items": {
"$ref": "#/definitions/PrometheusRuleGroup"
}
}
}
}
},
"PrometheusRemoteWriteTargetJSON": { "PrometheusRemoteWriteTargetJSON": {
"type": "object", "type": "object",
"properties": { "properties": {
@ -18534,6 +18563,55 @@
} }
} }
}, },
"PrometheusRule": {
"type": "object",
"properties": {
"Alert": {
"type": "string"
},
"Annotations": {
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"Expr": {
"type": "string"
},
"For": {
"type": "string"
},
"KeepFiringFor": {
"type": "string"
},
"Labels": {
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"Record": {
"type": "string"
}
}
},
"PrometheusRuleGroup": {
"type": "object",
"properties": {
"Interval": {
"$ref": "#/definitions/Duration"
},
"Name": {
"type": "string"
},
"Rules": {
"type": "array",
"items": {
"$ref": "#/definitions/PrometheusRule"
}
}
}
},
"Provenance": { "Provenance": {
"type": "string" "type": "string"
}, },
@ -22483,7 +22561,6 @@
} }
}, },
"alertGroups": { "alertGroups": {
"description": "AlertGroups alert groups",
"type": "array", "type": "array",
"items": { "items": {
"type": "object", "type": "object",

View File

@ -3957,6 +3957,20 @@
}, },
"type": "array" "type": "array"
}, },
"ConvertPrometheusResponse": {
"properties": {
"error": {
"type": "string"
},
"errorType": {
"type": "string"
},
"status": {
"type": "string"
}
},
"type": "object"
},
"CookiePreferences": { "CookiePreferences": {
"properties": { "properties": {
"analytics": {}, "analytics": {},
@ -8595,6 +8609,21 @@
}, },
"type": "object" "type": "object"
}, },
"PrometheusNamespace": {
"properties": {
"Body": {
"additionalProperties": {
"items": {
"$ref": "#/components/schemas/PrometheusRuleGroup"
},
"type": "array"
},
"description": "in: body",
"type": "object"
}
},
"type": "object"
},
"PrometheusRemoteWriteTargetJSON": { "PrometheusRemoteWriteTargetJSON": {
"properties": { "properties": {
"data_source_uid": { "data_source_uid": {
@ -8609,6 +8638,55 @@
}, },
"type": "object" "type": "object"
}, },
"PrometheusRule": {
"properties": {
"Alert": {
"type": "string"
},
"Annotations": {
"additionalProperties": {
"type": "string"
},
"type": "object"
},
"Expr": {
"type": "string"
},
"For": {
"type": "string"
},
"KeepFiringFor": {
"type": "string"
},
"Labels": {
"additionalProperties": {
"type": "string"
},
"type": "object"
},
"Record": {
"type": "string"
}
},
"type": "object"
},
"PrometheusRuleGroup": {
"properties": {
"Interval": {
"$ref": "#/components/schemas/Duration"
},
"Name": {
"type": "string"
},
"Rules": {
"items": {
"$ref": "#/components/schemas/PrometheusRule"
},
"type": "array"
}
},
"type": "object"
},
"Provenance": { "Provenance": {
"type": "string" "type": "string"
}, },
@ -12557,7 +12635,6 @@
"type": "object" "type": "object"
}, },
"alertGroups": { "alertGroups": {
"description": "AlertGroups alert groups",
"items": { "items": {
"$ref": "#/components/schemas/alertGroup" "$ref": "#/components/schemas/alertGroup"
}, },