Alerting: API paths for cortextool to import Loki rules (#101409)
Alerting: Legacy rules paths for cortextool
This commit is contained in:
@@ -125,26 +125,32 @@ func (api *API) authorize(method, path string) web.Handler {
|
||||
|
||||
// convert/prometheus API paths
|
||||
case http.MethodGet + "/api/convert/prometheus/config/v1/rules/{NamespaceTitle}/{Group}",
|
||||
http.MethodGet + "/api/convert/prometheus/config/v1/rules/{NamespaceTitle}":
|
||||
http.MethodGet + "/api/convert/api/prom/rules/{NamespaceTitle}/{Group}",
|
||||
http.MethodGet + "/api/convert/prometheus/config/v1/rules/{NamespaceTitle}",
|
||||
http.MethodGet + "/api/convert/api/prom/rules/{NamespaceTitle}":
|
||||
eval = ac.EvalAll(
|
||||
ac.EvalPermission(ac.ActionAlertingRuleRead),
|
||||
ac.EvalPermission(dashboards.ActionFoldersRead),
|
||||
)
|
||||
|
||||
case http.MethodGet + "/api/convert/prometheus/config/v1/rules":
|
||||
case http.MethodGet + "/api/convert/prometheus/config/v1/rules",
|
||||
http.MethodGet + "/api/convert/api/prom/rules":
|
||||
eval = ac.EvalAll(
|
||||
ac.EvalPermission(ac.ActionAlertingRuleRead),
|
||||
ac.EvalPermission(dashboards.ActionFoldersRead),
|
||||
)
|
||||
|
||||
case http.MethodPost + "/api/convert/prometheus/config/v1/rules/{NamespaceTitle}":
|
||||
case http.MethodPost + "/api/convert/prometheus/config/v1/rules/{NamespaceTitle}",
|
||||
http.MethodPost + "/api/convert/api/prom/rules/{NamespaceTitle}":
|
||||
eval = ac.EvalAll(
|
||||
ac.EvalPermission(ac.ActionAlertingRuleCreate),
|
||||
ac.EvalPermission(ac.ActionAlertingProvisioningSetStatus),
|
||||
)
|
||||
|
||||
case http.MethodDelete + "/api/convert/prometheus/config/v1/rules/{NamespaceTitle}/{Group}",
|
||||
http.MethodDelete + "/api/convert/prometheus/config/v1/rules/{NamespaceTitle}":
|
||||
http.MethodDelete + "/api/convert/api/prom/rules/{NamespaceTitle}/{Group}",
|
||||
http.MethodDelete + "/api/convert/prometheus/config/v1/rules/{NamespaceTitle}",
|
||||
http.MethodDelete + "/api/convert/api/prom/rules/{NamespaceTitle}":
|
||||
eval = ac.EvalAny(
|
||||
ac.EvalAll(
|
||||
ac.EvalPermission(ac.ActionAlertingRuleRead),
|
||||
|
||||
@@ -41,7 +41,7 @@ func TestAuthorize(t *testing.T) {
|
||||
}
|
||||
paths[p] = methods
|
||||
}
|
||||
require.Len(t, paths, 63)
|
||||
require.Len(t, paths, 66)
|
||||
|
||||
ac := acmock.New()
|
||||
api := &API{AccessControl: ac, FeatureManager: featuremgmt.WithFeatures()}
|
||||
|
||||
@@ -19,6 +19,12 @@ import (
|
||||
)
|
||||
|
||||
type ConvertPrometheusApi interface {
|
||||
RouteConvertPrometheusCortexDeleteNamespace(*contextmodel.ReqContext) response.Response
|
||||
RouteConvertPrometheusCortexDeleteRuleGroup(*contextmodel.ReqContext) response.Response
|
||||
RouteConvertPrometheusCortexGetNamespace(*contextmodel.ReqContext) response.Response
|
||||
RouteConvertPrometheusCortexGetRuleGroup(*contextmodel.ReqContext) response.Response
|
||||
RouteConvertPrometheusCortexGetRules(*contextmodel.ReqContext) response.Response
|
||||
RouteConvertPrometheusCortexPostRuleGroup(*contextmodel.ReqContext) response.Response
|
||||
RouteConvertPrometheusDeleteNamespace(*contextmodel.ReqContext) response.Response
|
||||
RouteConvertPrometheusDeleteRuleGroup(*contextmodel.ReqContext) response.Response
|
||||
RouteConvertPrometheusGetNamespace(*contextmodel.ReqContext) response.Response
|
||||
@@ -27,6 +33,36 @@ type ConvertPrometheusApi interface {
|
||||
RouteConvertPrometheusPostRuleGroup(*contextmodel.ReqContext) response.Response
|
||||
}
|
||||
|
||||
func (f *ConvertPrometheusApiHandler) RouteConvertPrometheusCortexDeleteNamespace(ctx *contextmodel.ReqContext) response.Response {
|
||||
// Parse Path Parameters
|
||||
namespaceTitleParam := web.Params(ctx.Req)[":NamespaceTitle"]
|
||||
return f.handleRouteConvertPrometheusCortexDeleteNamespace(ctx, namespaceTitleParam)
|
||||
}
|
||||
func (f *ConvertPrometheusApiHandler) RouteConvertPrometheusCortexDeleteRuleGroup(ctx *contextmodel.ReqContext) response.Response {
|
||||
// Parse Path Parameters
|
||||
namespaceTitleParam := web.Params(ctx.Req)[":NamespaceTitle"]
|
||||
groupParam := web.Params(ctx.Req)[":Group"]
|
||||
return f.handleRouteConvertPrometheusCortexDeleteRuleGroup(ctx, namespaceTitleParam, groupParam)
|
||||
}
|
||||
func (f *ConvertPrometheusApiHandler) RouteConvertPrometheusCortexGetNamespace(ctx *contextmodel.ReqContext) response.Response {
|
||||
// Parse Path Parameters
|
||||
namespaceTitleParam := web.Params(ctx.Req)[":NamespaceTitle"]
|
||||
return f.handleRouteConvertPrometheusCortexGetNamespace(ctx, namespaceTitleParam)
|
||||
}
|
||||
func (f *ConvertPrometheusApiHandler) RouteConvertPrometheusCortexGetRuleGroup(ctx *contextmodel.ReqContext) response.Response {
|
||||
// Parse Path Parameters
|
||||
namespaceTitleParam := web.Params(ctx.Req)[":NamespaceTitle"]
|
||||
groupParam := web.Params(ctx.Req)[":Group"]
|
||||
return f.handleRouteConvertPrometheusCortexGetRuleGroup(ctx, namespaceTitleParam, groupParam)
|
||||
}
|
||||
func (f *ConvertPrometheusApiHandler) RouteConvertPrometheusCortexGetRules(ctx *contextmodel.ReqContext) response.Response {
|
||||
return f.handleRouteConvertPrometheusCortexGetRules(ctx)
|
||||
}
|
||||
func (f *ConvertPrometheusApiHandler) RouteConvertPrometheusCortexPostRuleGroup(ctx *contextmodel.ReqContext) response.Response {
|
||||
// Parse Path Parameters
|
||||
namespaceTitleParam := web.Params(ctx.Req)[":NamespaceTitle"]
|
||||
return f.handleRouteConvertPrometheusCortexPostRuleGroup(ctx, namespaceTitleParam)
|
||||
}
|
||||
func (f *ConvertPrometheusApiHandler) RouteConvertPrometheusDeleteNamespace(ctx *contextmodel.ReqContext) response.Response {
|
||||
// Parse Path Parameters
|
||||
namespaceTitleParam := web.Params(ctx.Req)[":NamespaceTitle"]
|
||||
@@ -60,6 +96,78 @@ func (f *ConvertPrometheusApiHandler) RouteConvertPrometheusPostRuleGroup(ctx *c
|
||||
|
||||
func (api *API) RegisterConvertPrometheusApiEndpoints(srv ConvertPrometheusApi, m *metrics.API) {
|
||||
api.RouteRegister.Group("", func(group routing.RouteRegister) {
|
||||
group.Delete(
|
||||
toMacaronPath("/api/convert/api/prom/rules/{NamespaceTitle}"),
|
||||
requestmeta.SetOwner(requestmeta.TeamAlerting),
|
||||
requestmeta.SetSLOGroup(requestmeta.SLOGroupHighSlow),
|
||||
api.authorize(http.MethodDelete, "/api/convert/api/prom/rules/{NamespaceTitle}"),
|
||||
metrics.Instrument(
|
||||
http.MethodDelete,
|
||||
"/api/convert/api/prom/rules/{NamespaceTitle}",
|
||||
api.Hooks.Wrap(srv.RouteConvertPrometheusCortexDeleteNamespace),
|
||||
m,
|
||||
),
|
||||
)
|
||||
group.Delete(
|
||||
toMacaronPath("/api/convert/api/prom/rules/{NamespaceTitle}/{Group}"),
|
||||
requestmeta.SetOwner(requestmeta.TeamAlerting),
|
||||
requestmeta.SetSLOGroup(requestmeta.SLOGroupHighSlow),
|
||||
api.authorize(http.MethodDelete, "/api/convert/api/prom/rules/{NamespaceTitle}/{Group}"),
|
||||
metrics.Instrument(
|
||||
http.MethodDelete,
|
||||
"/api/convert/api/prom/rules/{NamespaceTitle}/{Group}",
|
||||
api.Hooks.Wrap(srv.RouteConvertPrometheusCortexDeleteRuleGroup),
|
||||
m,
|
||||
),
|
||||
)
|
||||
group.Get(
|
||||
toMacaronPath("/api/convert/api/prom/rules/{NamespaceTitle}"),
|
||||
requestmeta.SetOwner(requestmeta.TeamAlerting),
|
||||
requestmeta.SetSLOGroup(requestmeta.SLOGroupHighSlow),
|
||||
api.authorize(http.MethodGet, "/api/convert/api/prom/rules/{NamespaceTitle}"),
|
||||
metrics.Instrument(
|
||||
http.MethodGet,
|
||||
"/api/convert/api/prom/rules/{NamespaceTitle}",
|
||||
api.Hooks.Wrap(srv.RouteConvertPrometheusCortexGetNamespace),
|
||||
m,
|
||||
),
|
||||
)
|
||||
group.Get(
|
||||
toMacaronPath("/api/convert/api/prom/rules/{NamespaceTitle}/{Group}"),
|
||||
requestmeta.SetOwner(requestmeta.TeamAlerting),
|
||||
requestmeta.SetSLOGroup(requestmeta.SLOGroupHighSlow),
|
||||
api.authorize(http.MethodGet, "/api/convert/api/prom/rules/{NamespaceTitle}/{Group}"),
|
||||
metrics.Instrument(
|
||||
http.MethodGet,
|
||||
"/api/convert/api/prom/rules/{NamespaceTitle}/{Group}",
|
||||
api.Hooks.Wrap(srv.RouteConvertPrometheusCortexGetRuleGroup),
|
||||
m,
|
||||
),
|
||||
)
|
||||
group.Get(
|
||||
toMacaronPath("/api/convert/api/prom/rules"),
|
||||
requestmeta.SetOwner(requestmeta.TeamAlerting),
|
||||
requestmeta.SetSLOGroup(requestmeta.SLOGroupHighSlow),
|
||||
api.authorize(http.MethodGet, "/api/convert/api/prom/rules"),
|
||||
metrics.Instrument(
|
||||
http.MethodGet,
|
||||
"/api/convert/api/prom/rules",
|
||||
api.Hooks.Wrap(srv.RouteConvertPrometheusCortexGetRules),
|
||||
m,
|
||||
),
|
||||
)
|
||||
group.Post(
|
||||
toMacaronPath("/api/convert/api/prom/rules/{NamespaceTitle}"),
|
||||
requestmeta.SetOwner(requestmeta.TeamAlerting),
|
||||
requestmeta.SetSLOGroup(requestmeta.SLOGroupHighSlow),
|
||||
api.authorize(http.MethodPost, "/api/convert/api/prom/rules/{NamespaceTitle}"),
|
||||
metrics.Instrument(
|
||||
http.MethodPost,
|
||||
"/api/convert/api/prom/rules/{NamespaceTitle}",
|
||||
api.Hooks.Wrap(srv.RouteConvertPrometheusCortexPostRuleGroup),
|
||||
m,
|
||||
),
|
||||
)
|
||||
group.Delete(
|
||||
toMacaronPath("/api/convert/prometheus/config/v1/rules/{NamespaceTitle}"),
|
||||
requestmeta.SetOwner(requestmeta.TeamAlerting),
|
||||
|
||||
@@ -20,6 +20,7 @@ func NewConvertPrometheusApi(svc *ConvertPrometheusSrv) *ConvertPrometheusApiHan
|
||||
}
|
||||
}
|
||||
|
||||
// mimirtool
|
||||
func (f *ConvertPrometheusApiHandler) handleRouteConvertPrometheusGetRules(ctx *contextmodel.ReqContext) response.Response {
|
||||
return f.svc.RouteConvertPrometheusGetRules(ctx)
|
||||
}
|
||||
@@ -54,3 +55,28 @@ func (f *ConvertPrometheusApiHandler) handleRouteConvertPrometheusPostRuleGroup(
|
||||
|
||||
return f.svc.RouteConvertPrometheusPostRuleGroup(ctx, namespaceTitle, promGroup)
|
||||
}
|
||||
|
||||
// cortextool
|
||||
func (f *ConvertPrometheusApiHandler) handleRouteConvertPrometheusCortexGetRules(ctx *contextmodel.ReqContext) response.Response {
|
||||
return f.handleRouteConvertPrometheusGetRules(ctx)
|
||||
}
|
||||
|
||||
func (f *ConvertPrometheusApiHandler) handleRouteConvertPrometheusCortexDeleteNamespace(ctx *contextmodel.ReqContext, namespaceTitle string) response.Response {
|
||||
return f.handleRouteConvertPrometheusDeleteNamespace(ctx, namespaceTitle)
|
||||
}
|
||||
|
||||
func (f *ConvertPrometheusApiHandler) handleRouteConvertPrometheusCortexDeleteRuleGroup(ctx *contextmodel.ReqContext, namespaceTitle string, group string) response.Response {
|
||||
return f.handleRouteConvertPrometheusDeleteRuleGroup(ctx, namespaceTitle, group)
|
||||
}
|
||||
|
||||
func (f *ConvertPrometheusApiHandler) handleRouteConvertPrometheusCortexGetNamespace(ctx *contextmodel.ReqContext, namespaceTitle string) response.Response {
|
||||
return f.handleRouteConvertPrometheusGetNamespace(ctx, namespaceTitle)
|
||||
}
|
||||
|
||||
func (f *ConvertPrometheusApiHandler) handleRouteConvertPrometheusCortexGetRuleGroup(ctx *contextmodel.ReqContext, namespaceTitle string, group string) response.Response {
|
||||
return f.handleRouteConvertPrometheusGetRuleGroup(ctx, namespaceTitle, group)
|
||||
}
|
||||
|
||||
func (f *ConvertPrometheusApiHandler) handleRouteConvertPrometheusCortexPostRuleGroup(ctx *contextmodel.ReqContext, namespaceTitle string) response.Response {
|
||||
return f.handleRouteConvertPrometheusPostRuleGroup(ctx, namespaceTitle)
|
||||
}
|
||||
|
||||
@@ -4493,7 +4493,6 @@
|
||||
"type": "object"
|
||||
},
|
||||
"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\nThe Host field contains the host and port subcomponents of the URL.\nWhen the port is present, it is separated from the host with a colon.\nWhen the host is an IPv6 address, it must be enclosed in square brackets:\n\"[fe80::1]:80\". The [net.JoinHostPort] function combines a host and port\ninto a string suitable for the Host field, adding square brackets to\nthe host when necessary.\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 the [URL.EscapedPath] method, which preserves\nthe original encoding of Path.\n\nThe RawPath field is an optional field which is only set when the default\nencoding of Path is different from the escaped path. See the EscapedPath method\nfor more details.\n\nURL's String method uses the EscapedPath method to obtain the path.",
|
||||
"properties": {
|
||||
"ForceQuery": {
|
||||
"type": "boolean"
|
||||
@@ -4529,7 +4528,7 @@
|
||||
"$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"
|
||||
},
|
||||
"UpdateRuleGroupResponse": {
|
||||
@@ -4932,6 +4931,7 @@
|
||||
"type": "object"
|
||||
},
|
||||
"gettableAlerts": {
|
||||
"description": "GettableAlerts gettable alerts",
|
||||
"items": {
|
||||
"$ref": "#/definitions/gettableAlert",
|
||||
"type": "object"
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"github.com/prometheus/common/model"
|
||||
)
|
||||
|
||||
// Route for mimirtool
|
||||
// swagger:route GET /convert/prometheus/config/v1/rules convert_prometheus RouteConvertPrometheusGetRules
|
||||
//
|
||||
// Gets all Grafana-managed alert rules that were imported from Prometheus-compatible sources, grouped by namespace.
|
||||
@@ -16,6 +17,20 @@ import (
|
||||
// 403: ForbiddenError
|
||||
// 404: NotFound
|
||||
|
||||
// Route for cortextool
|
||||
// swagger:route GET /convert/api/prom/rules convert_prometheus RouteConvertPrometheusCortexGetRules
|
||||
//
|
||||
// Gets all Grafana-managed alert rules that were imported from Prometheus-compatible sources, grouped by namespace.
|
||||
//
|
||||
// Produces:
|
||||
// - application/yaml
|
||||
//
|
||||
// Responses:
|
||||
// 200: PrometheusNamespace
|
||||
// 403: ForbiddenError
|
||||
// 404: NotFound
|
||||
|
||||
// Route for mimirtool
|
||||
// swagger:route GET /convert/prometheus/config/v1/rules/{NamespaceTitle} convert_prometheus RouteConvertPrometheusGetNamespace
|
||||
//
|
||||
// Gets Grafana-managed alert rules that were imported from Prometheus-compatible sources for a specified namespace (folder).
|
||||
@@ -28,6 +43,20 @@ import (
|
||||
// 403: ForbiddenError
|
||||
// 404: NotFound
|
||||
|
||||
// Route for cortextool
|
||||
// swagger:route GET /convert/api/prom/rules/{NamespaceTitle} convert_prometheus RouteConvertPrometheusCortexGetNamespace
|
||||
//
|
||||
// Gets Grafana-managed alert rules that were imported from Prometheus-compatible sources for a specified namespace (folder).
|
||||
//
|
||||
// Produces:
|
||||
// - application/yaml
|
||||
//
|
||||
// Responses:
|
||||
// 200: PrometheusNamespace
|
||||
// 403: ForbiddenError
|
||||
// 404: NotFound
|
||||
|
||||
// Route for mimirtool
|
||||
// swagger:route GET /convert/prometheus/config/v1/rules/{NamespaceTitle}/{Group} convert_prometheus RouteConvertPrometheusGetRuleGroup
|
||||
//
|
||||
// Gets a single rule group in Prometheus-compatible format if it was imported from a Prometheus-compatible source.
|
||||
@@ -40,6 +69,20 @@ import (
|
||||
// 403: ForbiddenError
|
||||
// 404: NotFound
|
||||
|
||||
// Route for cortextool
|
||||
// swagger:route GET /convert/api/prom/rules/{NamespaceTitle}/{Group} convert_prometheus RouteConvertPrometheusCortexGetRuleGroup
|
||||
//
|
||||
// Gets a single rule group in Prometheus-compatible format if it was imported from a Prometheus-compatible source.
|
||||
//
|
||||
// Produces:
|
||||
// - application/yaml
|
||||
//
|
||||
// Responses:
|
||||
// 200: PrometheusRuleGroup
|
||||
// 403: ForbiddenError
|
||||
// 404: NotFound
|
||||
|
||||
// Route for mimirtool
|
||||
// swagger:route POST /convert/prometheus/config/v1/rules/{NamespaceTitle} convert_prometheus RouteConvertPrometheusPostRuleGroup
|
||||
//
|
||||
// Converts a Prometheus rule group into a Grafana rule group and creates or updates it within the specified namespace.
|
||||
@@ -59,6 +102,27 @@ import (
|
||||
// Extensions:
|
||||
// x-raw-request: true
|
||||
|
||||
// Route for cortextool
|
||||
// swagger:route POST /convert/api/prom/rules/{NamespaceTitle} convert_prometheus RouteConvertPrometheusCortexPostRuleGroup
|
||||
//
|
||||
// Converts a Prometheus rule group into a Grafana rule group and creates or updates it within the specified namespace.
|
||||
// If the group already exists and was not imported from a Prometheus-compatible source initially,
|
||||
// it will not be replaced and an error will be returned.
|
||||
//
|
||||
// Consumes:
|
||||
// - application/yaml
|
||||
//
|
||||
// Produces:
|
||||
// - application/json
|
||||
//
|
||||
// Responses:
|
||||
// 202: ConvertPrometheusResponse
|
||||
// 403: ForbiddenError
|
||||
//
|
||||
// Extensions:
|
||||
// x-raw-request: true
|
||||
|
||||
// Route for mimirtool
|
||||
// swagger:route DELETE /convert/prometheus/config/v1/rules/{NamespaceTitle} convert_prometheus RouteConvertPrometheusDeleteNamespace
|
||||
//
|
||||
// Deletes all rule groups that were imported from Prometheus-compatible sources within the specified namespace.
|
||||
@@ -70,6 +134,19 @@ import (
|
||||
// 202: ConvertPrometheusResponse
|
||||
// 403: ForbiddenError
|
||||
|
||||
// Route for cortextool
|
||||
// swagger:route DELETE /convert/api/prom/rules/{NamespaceTitle} convert_prometheus RouteConvertPrometheusCortexDeleteNamespace
|
||||
//
|
||||
// Deletes all rule groups that were imported from Prometheus-compatible sources within the specified namespace.
|
||||
//
|
||||
// Produces:
|
||||
// - application/json
|
||||
//
|
||||
// Responses:
|
||||
// 202: ConvertPrometheusResponse
|
||||
// 403: ForbiddenError
|
||||
|
||||
// Route for mimirtool
|
||||
// swagger:route DELETE /convert/prometheus/config/v1/rules/{NamespaceTitle}/{Group} convert_prometheus RouteConvertPrometheusDeleteRuleGroup
|
||||
//
|
||||
// Deletes a specific rule group if it was imported from a Prometheus-compatible source.
|
||||
@@ -81,7 +158,19 @@ import (
|
||||
// 202: ConvertPrometheusResponse
|
||||
// 403: ForbiddenError
|
||||
|
||||
// swagger:parameters RouteConvertPrometheusPostRuleGroup
|
||||
// Route for cortextool
|
||||
// swagger:route DELETE /convert/api/prom/rules/{NamespaceTitle}/{Group} convert_prometheus RouteConvertPrometheusCortexDeleteRuleGroup
|
||||
//
|
||||
// Deletes a specific rule group if it was imported from a Prometheus-compatible source.
|
||||
//
|
||||
// Produces:
|
||||
// - application/json
|
||||
//
|
||||
// Responses:
|
||||
// 202: ConvertPrometheusResponse
|
||||
// 403: ForbiddenError
|
||||
|
||||
// swagger:parameters RouteConvertPrometheusPostRuleGroup RouteConvertPrometheusCortexPostRuleGroup
|
||||
type RouteConvertPrometheusPostRuleGroupParams struct {
|
||||
// in: path
|
||||
NamespaceTitle string
|
||||
@@ -119,7 +208,7 @@ type PrometheusRule struct {
|
||||
Record string `yaml:"record,omitempty"`
|
||||
}
|
||||
|
||||
// swagger:parameters RouteConvertPrometheusDeleteRuleGroup RouteConvertPrometheusGetRuleGroup
|
||||
// swagger:parameters RouteConvertPrometheusDeleteRuleGroup RouteConvertPrometheusCortexDeleteRuleGroup RouteConvertPrometheusGetRuleGroup RouteConvertPrometheusCortexGetRuleGroup
|
||||
type RouteConvertPrometheusDeleteRuleGroupParams struct {
|
||||
// in: path
|
||||
NamespaceTitle string
|
||||
@@ -127,7 +216,7 @@ type RouteConvertPrometheusDeleteRuleGroupParams struct {
|
||||
Group string
|
||||
}
|
||||
|
||||
// swagger:parameters RouteConvertPrometheusDeleteNamespace RouteConvertPrometheusGetNamespace
|
||||
// swagger:parameters RouteConvertPrometheusDeleteNamespace RouteConvertPrometheusCortexDeleteNamespace RouteConvertPrometheusGetNamespace RouteConvertPrometheusCortexGetNamespace
|
||||
type RouteConvertPrometheusDeleteNamespaceParams struct {
|
||||
// in: path
|
||||
NamespaceTitle string
|
||||
|
||||
@@ -4493,6 +4493,7 @@
|
||||
"type": "object"
|
||||
},
|
||||
"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\nThe Host field contains the host and port subcomponents of the URL.\nWhen the port is present, it is separated from the host with a colon.\nWhen the host is an IPv6 address, it must be enclosed in square brackets:\n\"[fe80::1]:80\". The [net.JoinHostPort] function combines a host and port\ninto a string suitable for the Host field, adding square brackets to\nthe host when necessary.\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 the [URL.EscapedPath] method, which preserves\nthe original encoding of Path.\n\nThe RawPath field is an optional field which is only set when the default\nencoding of Path is different from the escaped path. See the EscapedPath method\nfor more details.\n\nURL's String method uses the EscapedPath method to obtain the path.",
|
||||
"properties": {
|
||||
"ForceQuery": {
|
||||
"type": "boolean"
|
||||
@@ -4528,7 +4529,7 @@
|
||||
"$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"
|
||||
},
|
||||
"UpdateRuleGroupResponse": {
|
||||
@@ -4770,6 +4771,7 @@
|
||||
"type": "object"
|
||||
},
|
||||
"alertGroups": {
|
||||
"description": "AlertGroups alert groups",
|
||||
"items": {
|
||||
"$ref": "#/definitions/alertGroup",
|
||||
"type": "object"
|
||||
@@ -5056,6 +5058,7 @@
|
||||
"type": "object"
|
||||
},
|
||||
"gettableSilences": {
|
||||
"description": "GettableSilences gettable silences",
|
||||
"items": {
|
||||
"$ref": "#/definitions/gettableSilence",
|
||||
"type": "object"
|
||||
@@ -6398,6 +6401,253 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"/convert/api/prom/rules": {
|
||||
"get": {
|
||||
"operationId": "RouteConvertPrometheusCortexGetRules",
|
||||
"produces": [
|
||||
"application/yaml"
|
||||
],
|
||||
"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 Grafana-managed alert rules that were imported from Prometheus-compatible sources, grouped by namespace.",
|
||||
"tags": [
|
||||
"convert_prometheus"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/convert/api/prom/rules/{NamespaceTitle}": {
|
||||
"delete": {
|
||||
"operationId": "RouteConvertPrometheusCortexDeleteNamespace",
|
||||
"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 that were imported from Prometheus-compatible sources within the specified namespace.",
|
||||
"tags": [
|
||||
"convert_prometheus"
|
||||
]
|
||||
},
|
||||
"get": {
|
||||
"operationId": "RouteConvertPrometheusCortexGetNamespace",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "path",
|
||||
"name": "NamespaceTitle",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"produces": [
|
||||
"application/yaml"
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "PrometheusNamespace",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/PrometheusNamespace"
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"description": "ForbiddenError",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/ForbiddenError"
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "NotFound",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/NotFound"
|
||||
}
|
||||
}
|
||||
},
|
||||
"summary": "Gets Grafana-managed alert rules that were imported from Prometheus-compatible sources for a specified namespace (folder).",
|
||||
"tags": [
|
||||
"convert_prometheus"
|
||||
]
|
||||
},
|
||||
"post": {
|
||||
"consumes": [
|
||||
"application/yaml"
|
||||
],
|
||||
"description": "If the group already exists and was not imported from a Prometheus-compatible source initially,\nit will not be replaced and an error will be returned.",
|
||||
"operationId": "RouteConvertPrometheusCortexPostRuleGroup",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "path",
|
||||
"name": "NamespaceTitle",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"in": "header",
|
||||
"name": "x-grafana-alerting-datasource-uid",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"in": "header",
|
||||
"name": "x-grafana-alerting-recording-rules-paused",
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"in": "header",
|
||||
"name": "x-grafana-alerting-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": "Converts a Prometheus rule group into a Grafana rule group and creates or updates it within the specified namespace.",
|
||||
"tags": [
|
||||
"convert_prometheus"
|
||||
],
|
||||
"x-raw-request": "true"
|
||||
}
|
||||
},
|
||||
"/convert/api/prom/rules/{NamespaceTitle}/{Group}": {
|
||||
"delete": {
|
||||
"operationId": "RouteConvertPrometheusCortexDeleteRuleGroup",
|
||||
"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 specific rule group if it was imported from a Prometheus-compatible source.",
|
||||
"tags": [
|
||||
"convert_prometheus"
|
||||
]
|
||||
},
|
||||
"get": {
|
||||
"operationId": "RouteConvertPrometheusCortexGetRuleGroup",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "path",
|
||||
"name": "NamespaceTitle",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"in": "path",
|
||||
"name": "Group",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"produces": [
|
||||
"application/yaml"
|
||||
],
|
||||
"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 single rule group in Prometheus-compatible format if it was imported from a Prometheus-compatible source.",
|
||||
"tags": [
|
||||
"convert_prometheus"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/convert/prometheus/config/v1/rules": {
|
||||
"get": {
|
||||
"operationId": "RouteConvertPrometheusGetRules",
|
||||
|
||||
@@ -1102,6 +1102,253 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/convert/api/prom/rules": {
|
||||
"get": {
|
||||
"produces": [
|
||||
"application/yaml"
|
||||
],
|
||||
"tags": [
|
||||
"convert_prometheus"
|
||||
],
|
||||
"summary": "Gets all Grafana-managed alert rules that were imported from Prometheus-compatible sources, grouped by namespace.",
|
||||
"operationId": "RouteConvertPrometheusCortexGetRules",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "PrometheusNamespace",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/PrometheusNamespace"
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"description": "ForbiddenError",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/ForbiddenError"
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "NotFound",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/NotFound"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/convert/api/prom/rules/{NamespaceTitle}": {
|
||||
"get": {
|
||||
"produces": [
|
||||
"application/yaml"
|
||||
],
|
||||
"tags": [
|
||||
"convert_prometheus"
|
||||
],
|
||||
"summary": "Gets Grafana-managed alert rules that were imported from Prometheus-compatible sources for a specified namespace (folder).",
|
||||
"operationId": "RouteConvertPrometheusCortexGetNamespace",
|
||||
"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": {
|
||||
"description": "If the group already exists and was not imported from a Prometheus-compatible source initially,\nit will not be replaced and an error will be returned.",
|
||||
"consumes": [
|
||||
"application/yaml"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"convert_prometheus"
|
||||
],
|
||||
"summary": "Converts a Prometheus rule group into a Grafana rule group and creates or updates it within the specified namespace.",
|
||||
"operationId": "RouteConvertPrometheusCortexPostRuleGroup",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"name": "NamespaceTitle",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "x-grafana-alerting-datasource-uid",
|
||||
"in": "header"
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"name": "x-grafana-alerting-recording-rules-paused",
|
||||
"in": "header"
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"name": "x-grafana-alerting-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 that were imported from Prometheus-compatible sources within the specified namespace.",
|
||||
"operationId": "RouteConvertPrometheusCortexDeleteNamespace",
|
||||
"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/api/prom/rules/{NamespaceTitle}/{Group}": {
|
||||
"get": {
|
||||
"produces": [
|
||||
"application/yaml"
|
||||
],
|
||||
"tags": [
|
||||
"convert_prometheus"
|
||||
],
|
||||
"summary": "Gets a single rule group in Prometheus-compatible format if it was imported from a Prometheus-compatible source.",
|
||||
"operationId": "RouteConvertPrometheusCortexGetRuleGroup",
|
||||
"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 specific rule group if it was imported from a Prometheus-compatible source.",
|
||||
"operationId": "RouteConvertPrometheusCortexDeleteRuleGroup",
|
||||
"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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/convert/prometheus/config/v1/rules": {
|
||||
"get": {
|
||||
"produces": [
|
||||
@@ -8434,8 +8681,9 @@
|
||||
}
|
||||
},
|
||||
"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\nThe Host field contains the host and port subcomponents of the URL.\nWhen the port is present, it is separated from the host with a colon.\nWhen the host is an IPv6 address, it must be enclosed in square brackets:\n\"[fe80::1]:80\". The [net.JoinHostPort] function combines a host and port\ninto a string suitable for the Host field, adding square brackets to\nthe host when necessary.\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 the [URL.EscapedPath] method, which preserves\nthe original encoding of Path.\n\nThe RawPath field is an optional field which is only set when the default\nencoding of Path is different from the escaped path. See the EscapedPath method\nfor more details.\n\nURL's String method uses the EscapedPath method to obtain the path.",
|
||||
"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"
|
||||
@@ -8711,6 +8959,7 @@
|
||||
}
|
||||
},
|
||||
"alertGroups": {
|
||||
"description": "AlertGroups alert groups",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
@@ -8997,6 +9246,7 @@
|
||||
}
|
||||
},
|
||||
"gettableSilences": {
|
||||
"description": "GettableSilences gettable silences",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
|
||||
@@ -99,283 +99,315 @@ var (
|
||||
)
|
||||
|
||||
func TestIntegrationConvertPrometheusEndpoints(t *testing.T) {
|
||||
testinfra.SQLiteIntegrationTest(t)
|
||||
runTest := func(t *testing.T, enableLokiPaths bool) {
|
||||
testinfra.SQLiteIntegrationTest(t)
|
||||
|
||||
// Setup Grafana and its Database
|
||||
dir, gpath := testinfra.CreateGrafDir(t, testinfra.GrafanaOpts{
|
||||
DisableLegacyAlerting: true,
|
||||
EnableUnifiedAlerting: true,
|
||||
DisableAnonymous: true,
|
||||
AppModeProduction: true,
|
||||
EnableFeatureToggles: []string{"alertingConversionAPI"},
|
||||
// Setup Grafana and its Database
|
||||
dir, gpath := testinfra.CreateGrafDir(t, testinfra.GrafanaOpts{
|
||||
DisableLegacyAlerting: true,
|
||||
EnableUnifiedAlerting: true,
|
||||
DisableAnonymous: true,
|
||||
AppModeProduction: true,
|
||||
EnableFeatureToggles: []string{"alertingConversionAPI"},
|
||||
})
|
||||
|
||||
grafanaListedAddr, env := testinfra.StartGrafanaEnv(t, dir, gpath)
|
||||
|
||||
// Create users to make authenticated requests
|
||||
createUser(t, env.SQLStore, env.Cfg, user.CreateUserCommand{
|
||||
DefaultOrgRole: string(org.RoleAdmin),
|
||||
Password: "password",
|
||||
Login: "admin",
|
||||
})
|
||||
apiClient := newAlertingApiClient(grafanaListedAddr, "admin", "password")
|
||||
apiClient.prometheusConversionUseLokiPaths = enableLokiPaths
|
||||
|
||||
createUser(t, env.SQLStore, env.Cfg, user.CreateUserCommand{
|
||||
DefaultOrgRole: string(org.RoleViewer),
|
||||
Password: "password",
|
||||
Login: "viewer",
|
||||
})
|
||||
viewerClient := newAlertingApiClient(grafanaListedAddr, "viewer", "password")
|
||||
|
||||
namespace1 := "test-namespace-1"
|
||||
namespace2 := "test-namespace-2"
|
||||
|
||||
ds := apiClient.CreateDatasource(t, datasources.DS_PROMETHEUS)
|
||||
|
||||
t.Run("create rule groups and get them back", func(t *testing.T) {
|
||||
_, status, body := apiClient.ConvertPrometheusPostRuleGroup(t, namespace1, ds.Body.Datasource.UID, promGroup1, nil)
|
||||
requireStatusCode(t, http.StatusAccepted, status, body)
|
||||
_, status, body = apiClient.ConvertPrometheusPostRuleGroup(t, namespace1, ds.Body.Datasource.UID, promGroup2, nil)
|
||||
requireStatusCode(t, http.StatusAccepted, status, body)
|
||||
|
||||
// create a third group in a different namespace
|
||||
_, status, body = apiClient.ConvertPrometheusPostRuleGroup(t, namespace2, ds.Body.Datasource.UID, promGroup3, nil)
|
||||
requireStatusCode(t, http.StatusAccepted, status, body)
|
||||
|
||||
// And a non-provisioned rule in another namespace
|
||||
namespace3UID := util.GenerateShortUID()
|
||||
apiClient.CreateFolder(t, namespace3UID, "folder")
|
||||
createRule(t, apiClient, namespace3UID)
|
||||
|
||||
// Now get the first group
|
||||
group1 := apiClient.ConvertPrometheusGetRuleGroupRules(t, namespace1, promGroup1.Name)
|
||||
require.Equal(t, promGroup1, group1)
|
||||
|
||||
// Get namespace1
|
||||
ns1 := apiClient.ConvertPrometheusGetNamespaceRules(t, namespace1)
|
||||
expectedNs1 := map[string][]apimodels.PrometheusRuleGroup{
|
||||
namespace1: {promGroup1, promGroup2},
|
||||
}
|
||||
require.Equal(t, expectedNs1, ns1)
|
||||
|
||||
// Get all namespaces
|
||||
namespaces := apiClient.ConvertPrometheusGetAllRules(t)
|
||||
expectedNamespaces := map[string][]apimodels.PrometheusRuleGroup{
|
||||
namespace1: {promGroup1, promGroup2},
|
||||
namespace2: {promGroup3},
|
||||
}
|
||||
require.Equal(t, expectedNamespaces, namespaces)
|
||||
})
|
||||
|
||||
t.Run("without permissions to create folders cannot create rule groups either", func(t *testing.T) {
|
||||
_, status, raw := viewerClient.ConvertPrometheusPostRuleGroup(t, namespace1, ds.Body.Datasource.UID, promGroup1, nil)
|
||||
requireStatusCode(t, http.StatusForbidden, status, raw)
|
||||
})
|
||||
|
||||
t.Run("delete one rule group", func(t *testing.T) {
|
||||
_, status, body := apiClient.ConvertPrometheusPostRuleGroup(t, namespace1, ds.Body.Datasource.UID, promGroup1, nil)
|
||||
requireStatusCode(t, http.StatusAccepted, status, body)
|
||||
_, status, body = apiClient.ConvertPrometheusPostRuleGroup(t, namespace1, ds.Body.Datasource.UID, promGroup2, nil)
|
||||
requireStatusCode(t, http.StatusAccepted, status, body)
|
||||
_, status, body = apiClient.ConvertPrometheusPostRuleGroup(t, namespace2, ds.Body.Datasource.UID, promGroup3, nil)
|
||||
requireStatusCode(t, http.StatusAccepted, status, body)
|
||||
|
||||
apiClient.ConvertPrometheusDeleteRuleGroup(t, namespace1, promGroup1.Name)
|
||||
|
||||
// Check that the promGroup2 and promGroup3 are still there
|
||||
namespaces := apiClient.ConvertPrometheusGetAllRules(t)
|
||||
expectedNamespaces := map[string][]apimodels.PrometheusRuleGroup{
|
||||
namespace1: {promGroup2},
|
||||
namespace2: {promGroup3},
|
||||
}
|
||||
require.Equal(t, expectedNamespaces, namespaces)
|
||||
|
||||
// Delete the second namespace
|
||||
apiClient.ConvertPrometheusDeleteNamespace(t, namespace2)
|
||||
|
||||
// Check that only the first namespace is left
|
||||
namespaces = apiClient.ConvertPrometheusGetAllRules(t)
|
||||
expectedNamespaces = map[string][]apimodels.PrometheusRuleGroup{
|
||||
namespace1: {promGroup2},
|
||||
}
|
||||
require.Equal(t, expectedNamespaces, namespaces)
|
||||
})
|
||||
}
|
||||
|
||||
t.Run("with the mimirtool paths", func(t *testing.T) {
|
||||
runTest(t, false)
|
||||
})
|
||||
|
||||
grafanaListedAddr, env := testinfra.StartGrafanaEnv(t, dir, gpath)
|
||||
|
||||
// Create users to make authenticated requests
|
||||
createUser(t, env.SQLStore, env.Cfg, user.CreateUserCommand{
|
||||
DefaultOrgRole: string(org.RoleAdmin),
|
||||
Password: "password",
|
||||
Login: "admin",
|
||||
})
|
||||
apiClient := newAlertingApiClient(grafanaListedAddr, "admin", "password")
|
||||
|
||||
createUser(t, env.SQLStore, env.Cfg, user.CreateUserCommand{
|
||||
DefaultOrgRole: string(org.RoleViewer),
|
||||
Password: "password",
|
||||
Login: "viewer",
|
||||
})
|
||||
viewerClient := newAlertingApiClient(grafanaListedAddr, "viewer", "password")
|
||||
|
||||
namespace1 := "test-namespace-1"
|
||||
namespace2 := "test-namespace-2"
|
||||
|
||||
ds := apiClient.CreateDatasource(t, datasources.DS_PROMETHEUS)
|
||||
|
||||
t.Run("create rule groups and get them back", func(t *testing.T) {
|
||||
_, status, body := apiClient.ConvertPrometheusPostRuleGroup(t, namespace1, ds.Body.Datasource.UID, promGroup1, nil)
|
||||
requireStatusCode(t, http.StatusAccepted, status, body)
|
||||
_, status, body = apiClient.ConvertPrometheusPostRuleGroup(t, namespace1, ds.Body.Datasource.UID, promGroup2, nil)
|
||||
requireStatusCode(t, http.StatusAccepted, status, body)
|
||||
|
||||
// create a third group in a different namespace
|
||||
_, status, body = apiClient.ConvertPrometheusPostRuleGroup(t, namespace2, ds.Body.Datasource.UID, promGroup3, nil)
|
||||
requireStatusCode(t, http.StatusAccepted, status, body)
|
||||
|
||||
// And a non-provisioned rule in another namespace
|
||||
namespace3UID := util.GenerateShortUID()
|
||||
apiClient.CreateFolder(t, namespace3UID, "folder")
|
||||
createRule(t, apiClient, namespace3UID)
|
||||
|
||||
// Now get the first group
|
||||
group1 := apiClient.ConvertPrometheusGetRuleGroupRules(t, namespace1, promGroup1.Name)
|
||||
require.Equal(t, promGroup1, group1)
|
||||
|
||||
// Get namespace1
|
||||
ns1 := apiClient.ConvertPrometheusGetNamespaceRules(t, namespace1)
|
||||
expectedNs1 := map[string][]apimodels.PrometheusRuleGroup{
|
||||
namespace1: {promGroup1, promGroup2},
|
||||
}
|
||||
require.Equal(t, expectedNs1, ns1)
|
||||
|
||||
// Get all namespaces
|
||||
namespaces := apiClient.ConvertPrometheusGetAllRules(t)
|
||||
expectedNamespaces := map[string][]apimodels.PrometheusRuleGroup{
|
||||
namespace1: {promGroup1, promGroup2},
|
||||
namespace2: {promGroup3},
|
||||
}
|
||||
require.Equal(t, expectedNamespaces, namespaces)
|
||||
})
|
||||
|
||||
t.Run("without permissions to create folders cannot create rule groups either", func(t *testing.T) {
|
||||
_, status, raw := viewerClient.ConvertPrometheusPostRuleGroup(t, namespace1, ds.Body.Datasource.UID, promGroup1, nil)
|
||||
requireStatusCode(t, http.StatusForbidden, status, raw)
|
||||
})
|
||||
|
||||
t.Run("delete one rule group", func(t *testing.T) {
|
||||
_, status, body := apiClient.ConvertPrometheusPostRuleGroup(t, namespace1, ds.Body.Datasource.UID, promGroup1, nil)
|
||||
requireStatusCode(t, http.StatusAccepted, status, body)
|
||||
_, status, body = apiClient.ConvertPrometheusPostRuleGroup(t, namespace1, ds.Body.Datasource.UID, promGroup2, nil)
|
||||
requireStatusCode(t, http.StatusAccepted, status, body)
|
||||
_, status, body = apiClient.ConvertPrometheusPostRuleGroup(t, namespace2, ds.Body.Datasource.UID, promGroup3, nil)
|
||||
requireStatusCode(t, http.StatusAccepted, status, body)
|
||||
|
||||
apiClient.ConvertPrometheusDeleteRuleGroup(t, namespace1, promGroup1.Name)
|
||||
|
||||
// Check that the promGroup2 and promGroup3 are still there
|
||||
namespaces := apiClient.ConvertPrometheusGetAllRules(t)
|
||||
expectedNamespaces := map[string][]apimodels.PrometheusRuleGroup{
|
||||
namespace1: {promGroup2},
|
||||
namespace2: {promGroup3},
|
||||
}
|
||||
require.Equal(t, expectedNamespaces, namespaces)
|
||||
|
||||
// Delete the second namespace
|
||||
apiClient.ConvertPrometheusDeleteNamespace(t, namespace2)
|
||||
|
||||
// Check that only the first namespace is left
|
||||
namespaces = apiClient.ConvertPrometheusGetAllRules(t)
|
||||
expectedNamespaces = map[string][]apimodels.PrometheusRuleGroup{
|
||||
namespace1: {promGroup2},
|
||||
}
|
||||
require.Equal(t, expectedNamespaces, namespaces)
|
||||
t.Run("with the cortextool Loki paths", func(t *testing.T) {
|
||||
runTest(t, true)
|
||||
})
|
||||
}
|
||||
|
||||
func TestIntegrationConvertPrometheusEndpoints_Conflict(t *testing.T) {
|
||||
testinfra.SQLiteIntegrationTest(t)
|
||||
runTest := func(t *testing.T, enableLokiPaths bool) {
|
||||
testinfra.SQLiteIntegrationTest(t)
|
||||
|
||||
// Setup Grafana and its Database
|
||||
dir, gpath := testinfra.CreateGrafDir(t, testinfra.GrafanaOpts{
|
||||
DisableLegacyAlerting: true,
|
||||
EnableUnifiedAlerting: true,
|
||||
DisableAnonymous: true,
|
||||
AppModeProduction: true,
|
||||
EnableFeatureToggles: []string{"alertingConversionAPI"},
|
||||
})
|
||||
// Setup Grafana and its Database
|
||||
dir, gpath := testinfra.CreateGrafDir(t, testinfra.GrafanaOpts{
|
||||
DisableLegacyAlerting: true,
|
||||
EnableUnifiedAlerting: true,
|
||||
DisableAnonymous: true,
|
||||
AppModeProduction: true,
|
||||
EnableFeatureToggles: []string{"alertingConversionAPI"},
|
||||
})
|
||||
|
||||
grafanaListedAddr, env := testinfra.StartGrafanaEnv(t, dir, gpath)
|
||||
grafanaListedAddr, env := testinfra.StartGrafanaEnv(t, dir, gpath)
|
||||
|
||||
// Create users to make authenticated requests
|
||||
createUser(t, env.SQLStore, env.Cfg, user.CreateUserCommand{
|
||||
DefaultOrgRole: string(org.RoleAdmin),
|
||||
Password: "password",
|
||||
Login: "admin",
|
||||
})
|
||||
apiClient := newAlertingApiClient(grafanaListedAddr, "admin", "password")
|
||||
// Create users to make authenticated requests
|
||||
createUser(t, env.SQLStore, env.Cfg, user.CreateUserCommand{
|
||||
DefaultOrgRole: string(org.RoleAdmin),
|
||||
Password: "password",
|
||||
Login: "admin",
|
||||
})
|
||||
apiClient := newAlertingApiClient(grafanaListedAddr, "admin", "password")
|
||||
apiClient.prometheusConversionUseLokiPaths = enableLokiPaths
|
||||
|
||||
createUser(t, env.SQLStore, env.Cfg, user.CreateUserCommand{
|
||||
DefaultOrgRole: string(org.RoleViewer),
|
||||
Password: "password",
|
||||
Login: "viewer",
|
||||
})
|
||||
createUser(t, env.SQLStore, env.Cfg, user.CreateUserCommand{
|
||||
DefaultOrgRole: string(org.RoleViewer),
|
||||
Password: "password",
|
||||
Login: "viewer",
|
||||
})
|
||||
|
||||
namespace1 := "test-namespace-1"
|
||||
namespace1 := "test-namespace-1"
|
||||
|
||||
ds := apiClient.CreateDatasource(t, datasources.DS_PROMETHEUS)
|
||||
ds := apiClient.CreateDatasource(t, datasources.DS_PROMETHEUS)
|
||||
|
||||
t.Run("cannot overwrite a rule group with different provenance", func(t *testing.T) {
|
||||
// Create a rule group using the provisioning API and then try to overwrite it
|
||||
// using the Prometheus Conversion API. It should fail because the provenance
|
||||
// we set for rules in these two APIs is different and we check that when updating.
|
||||
provisionedRuleGroup := apimodels.AlertRuleGroup{
|
||||
Title: promGroup1.Name,
|
||||
Interval: 60,
|
||||
FolderUID: namespace1,
|
||||
Rules: []apimodels.ProvisionedAlertRule{
|
||||
{
|
||||
Title: "Rule1",
|
||||
OrgID: 1,
|
||||
RuleGroup: promGroup1.Name,
|
||||
Condition: "A",
|
||||
NoDataState: apimodels.Alerting,
|
||||
ExecErrState: apimodels.AlertingErrState,
|
||||
For: prommodel.Duration(time.Duration(60) * time.Second),
|
||||
Data: []apimodels.AlertQuery{
|
||||
{
|
||||
RefID: "A",
|
||||
RelativeTimeRange: apimodels.RelativeTimeRange{
|
||||
From: apimodels.Duration(time.Duration(5) * time.Hour),
|
||||
To: apimodels.Duration(time.Duration(3) * time.Hour),
|
||||
t.Run("cannot overwrite a rule group with different provenance", func(t *testing.T) {
|
||||
// Create a rule group using the provisioning API and then try to overwrite it
|
||||
// using the Prometheus Conversion API. It should fail because the provenance
|
||||
// we set for rules in these two APIs is different and we check that when updating.
|
||||
provisionedRuleGroup := apimodels.AlertRuleGroup{
|
||||
Title: promGroup1.Name,
|
||||
Interval: 60,
|
||||
FolderUID: namespace1,
|
||||
Rules: []apimodels.ProvisionedAlertRule{
|
||||
{
|
||||
Title: "Rule1",
|
||||
OrgID: 1,
|
||||
RuleGroup: promGroup1.Name,
|
||||
Condition: "A",
|
||||
NoDataState: apimodels.Alerting,
|
||||
ExecErrState: apimodels.AlertingErrState,
|
||||
For: prommodel.Duration(time.Duration(60) * time.Second),
|
||||
Data: []apimodels.AlertQuery{
|
||||
{
|
||||
RefID: "A",
|
||||
RelativeTimeRange: apimodels.RelativeTimeRange{
|
||||
From: apimodels.Duration(time.Duration(5) * time.Hour),
|
||||
To: apimodels.Duration(time.Duration(3) * time.Hour),
|
||||
},
|
||||
DatasourceUID: expr.DatasourceUID,
|
||||
Model: json.RawMessage([]byte(`{"type":"math","expression":"2 + 3 \u003e 1"}`)),
|
||||
},
|
||||
DatasourceUID: expr.DatasourceUID,
|
||||
Model: json.RawMessage([]byte(`{"type":"math","expression":"2 + 3 \u003e 1"}`)),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Create the folder
|
||||
apiClient.CreateFolder(t, namespace1, namespace1)
|
||||
// Create rule in the root folder using another API
|
||||
_, status, response := apiClient.CreateOrUpdateRuleGroupProvisioning(t, provisionedRuleGroup)
|
||||
require.Equalf(t, http.StatusOK, status, response)
|
||||
// Create the folder
|
||||
apiClient.CreateFolder(t, namespace1, namespace1)
|
||||
// Create rule in the root folder using another API
|
||||
_, status, response := apiClient.CreateOrUpdateRuleGroupProvisioning(t, provisionedRuleGroup)
|
||||
require.Equalf(t, http.StatusOK, status, response)
|
||||
|
||||
// Should fail to post the group
|
||||
_, status, body := apiClient.ConvertPrometheusPostRuleGroup(t, namespace1, ds.Body.Datasource.UID, promGroup1, nil)
|
||||
requireStatusCode(t, http.StatusConflict, status, body)
|
||||
// Should fail to post the group
|
||||
_, status, body := apiClient.ConvertPrometheusPostRuleGroup(t, namespace1, ds.Body.Datasource.UID, promGroup1, nil)
|
||||
requireStatusCode(t, http.StatusConflict, status, body)
|
||||
})
|
||||
}
|
||||
|
||||
t.Run("with the mimirtool paths", func(t *testing.T) {
|
||||
runTest(t, false)
|
||||
})
|
||||
|
||||
t.Run("with the cortextool Loki paths", func(t *testing.T) {
|
||||
runTest(t, true)
|
||||
})
|
||||
}
|
||||
|
||||
func TestIntegrationConvertPrometheusEndpoints_CreatePausedRules(t *testing.T) {
|
||||
testinfra.SQLiteIntegrationTest(t)
|
||||
runTest := func(t *testing.T, enableLokiPaths bool) {
|
||||
testinfra.SQLiteIntegrationTest(t)
|
||||
|
||||
// Setup Grafana and its Database
|
||||
dir, path := testinfra.CreateGrafDir(t, testinfra.GrafanaOpts{
|
||||
DisableLegacyAlerting: true,
|
||||
EnableUnifiedAlerting: true,
|
||||
DisableAnonymous: true,
|
||||
AppModeProduction: true,
|
||||
EnableFeatureToggles: []string{"alertingConversionAPI"},
|
||||
})
|
||||
// Setup Grafana and its Database
|
||||
dir, path := testinfra.CreateGrafDir(t, testinfra.GrafanaOpts{
|
||||
DisableLegacyAlerting: true,
|
||||
EnableUnifiedAlerting: true,
|
||||
DisableAnonymous: true,
|
||||
AppModeProduction: true,
|
||||
EnableFeatureToggles: []string{"alertingConversionAPI"},
|
||||
})
|
||||
|
||||
grafanaListedAddr, env := testinfra.StartGrafanaEnv(t, dir, path)
|
||||
grafanaListedAddr, env := testinfra.StartGrafanaEnv(t, dir, path)
|
||||
|
||||
// Create users to make authenticated requests
|
||||
createUser(t, env.SQLStore, env.Cfg, user.CreateUserCommand{
|
||||
DefaultOrgRole: string(org.RoleAdmin),
|
||||
Password: "password",
|
||||
Login: "admin",
|
||||
})
|
||||
apiClient := newAlertingApiClient(grafanaListedAddr, "admin", "password")
|
||||
// Create users to make authenticated requests
|
||||
createUser(t, env.SQLStore, env.Cfg, user.CreateUserCommand{
|
||||
DefaultOrgRole: string(org.RoleAdmin),
|
||||
Password: "password",
|
||||
Login: "admin",
|
||||
})
|
||||
apiClient := newAlertingApiClient(grafanaListedAddr, "admin", "password")
|
||||
|
||||
ds := apiClient.CreateDatasource(t, datasources.DS_PROMETHEUS)
|
||||
ds := apiClient.CreateDatasource(t, datasources.DS_PROMETHEUS)
|
||||
|
||||
namespace1 := "test-namespace-1"
|
||||
namespace1 := "test-namespace-1"
|
||||
|
||||
namespace1UID := util.GenerateShortUID()
|
||||
apiClient.CreateFolder(t, namespace1UID, namespace1)
|
||||
namespace1UID := util.GenerateShortUID()
|
||||
apiClient.CreateFolder(t, namespace1UID, namespace1)
|
||||
|
||||
t.Run("when pausing header is set, rules should be paused", func(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
recordingPaused bool
|
||||
alertPaused bool
|
||||
}{
|
||||
{
|
||||
name: "do not pause rules",
|
||||
recordingPaused: false,
|
||||
alertPaused: false,
|
||||
},
|
||||
{
|
||||
name: "pause recording rules",
|
||||
recordingPaused: true,
|
||||
alertPaused: false,
|
||||
},
|
||||
{
|
||||
name: "pause alert rules",
|
||||
recordingPaused: false,
|
||||
alertPaused: true,
|
||||
},
|
||||
{
|
||||
name: "pause both recording and alert rules",
|
||||
recordingPaused: true,
|
||||
alertPaused: true,
|
||||
},
|
||||
}
|
||||
t.Run("when pausing header is set, rules should be paused", func(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
recordingPaused bool
|
||||
alertPaused bool
|
||||
}{
|
||||
{
|
||||
name: "do not pause rules",
|
||||
recordingPaused: false,
|
||||
alertPaused: false,
|
||||
},
|
||||
{
|
||||
name: "pause recording rules",
|
||||
recordingPaused: true,
|
||||
alertPaused: false,
|
||||
},
|
||||
{
|
||||
name: "pause alert rules",
|
||||
recordingPaused: false,
|
||||
alertPaused: true,
|
||||
},
|
||||
{
|
||||
name: "pause both recording and alert rules",
|
||||
recordingPaused: true,
|
||||
alertPaused: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
headers := map[string]string{}
|
||||
if tc.recordingPaused {
|
||||
headers["X-Grafana-Alerting-Recording-Rules-Paused"] = "true"
|
||||
}
|
||||
if tc.alertPaused {
|
||||
headers["X-Grafana-Alerting-Alert-Rules-Paused"] = "true"
|
||||
}
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
headers := map[string]string{}
|
||||
if tc.recordingPaused {
|
||||
headers["X-Grafana-Alerting-Recording-Rules-Paused"] = "true"
|
||||
}
|
||||
if tc.alertPaused {
|
||||
headers["X-Grafana-Alerting-Alert-Rules-Paused"] = "true"
|
||||
}
|
||||
|
||||
apiClient.ConvertPrometheusPostRuleGroup(t, namespace1, ds.Body.Datasource.UID, promGroup1, headers)
|
||||
apiClient.ConvertPrometheusPostRuleGroup(t, namespace1, ds.Body.Datasource.UID, promGroup1, headers)
|
||||
|
||||
gr, _, _ := apiClient.GetRulesGroupWithStatus(t, namespace1UID, promGroup1.Name)
|
||||
gr, _, _ := apiClient.GetRulesGroupWithStatus(t, namespace1UID, promGroup1.Name)
|
||||
|
||||
require.Len(t, gr.Rules, 3)
|
||||
require.Len(t, gr.Rules, 3)
|
||||
|
||||
pausedRecordingRules := 0
|
||||
pausedAlertRules := 0
|
||||
pausedRecordingRules := 0
|
||||
pausedAlertRules := 0
|
||||
|
||||
for _, rule := range gr.Rules {
|
||||
if rule.GrafanaManagedAlert.IsPaused {
|
||||
if rule.GrafanaManagedAlert.Record != nil {
|
||||
pausedRecordingRules++
|
||||
} else {
|
||||
pausedAlertRules++
|
||||
for _, rule := range gr.Rules {
|
||||
if rule.GrafanaManagedAlert.IsPaused {
|
||||
if rule.GrafanaManagedAlert.Record != nil {
|
||||
pausedRecordingRules++
|
||||
} else {
|
||||
pausedAlertRules++
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if tc.recordingPaused {
|
||||
require.Equal(t, 1, pausedRecordingRules)
|
||||
} else {
|
||||
require.Equal(t, 0, pausedRecordingRules)
|
||||
}
|
||||
if tc.recordingPaused {
|
||||
require.Equal(t, 1, pausedRecordingRules)
|
||||
} else {
|
||||
require.Equal(t, 0, pausedRecordingRules)
|
||||
}
|
||||
|
||||
if tc.alertPaused {
|
||||
require.Equal(t, 2, pausedAlertRules)
|
||||
} else {
|
||||
require.Equal(t, 0, pausedAlertRules)
|
||||
}
|
||||
})
|
||||
}
|
||||
if tc.alertPaused {
|
||||
require.Equal(t, 2, pausedAlertRules)
|
||||
} else {
|
||||
require.Equal(t, 0, pausedAlertRules)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
t.Run("with the mimirtool paths", func(t *testing.T) {
|
||||
runTest(t, false)
|
||||
})
|
||||
|
||||
t.Run("with the cortextool Loki paths", func(t *testing.T) {
|
||||
runTest(t, true)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -254,7 +254,8 @@ func convertGettableGrafanaRuleToPostable(gettable *apimodels.GettableGrafanaRul
|
||||
}
|
||||
|
||||
type apiClient struct {
|
||||
url string
|
||||
url string
|
||||
prometheusConversionUseLokiPaths bool
|
||||
}
|
||||
|
||||
type LegacyApiClient struct {
|
||||
@@ -1121,7 +1122,13 @@ func (a apiClient) ConvertPrometheusPostRuleGroup(t *testing.T, namespaceTitle,
|
||||
|
||||
func (a apiClient) ConvertPrometheusGetRuleGroupRules(t *testing.T, namespaceTitle, groupName string) apimodels.PrometheusRuleGroup {
|
||||
t.Helper()
|
||||
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/api/convert/prometheus/config/v1/rules/%s/%s", a.url, namespaceTitle, groupName), nil)
|
||||
|
||||
path := "%s/api/convert/prometheus/config/v1/rules/%s/%s"
|
||||
if a.prometheusConversionUseLokiPaths {
|
||||
path = "%s/api/convert/api/prom/rules/%s/%s"
|
||||
}
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf(path, a.url, namespaceTitle, groupName), nil)
|
||||
require.NoError(t, err)
|
||||
rule, status, raw := sendRequestYAML[apimodels.PrometheusRuleGroup](t, req, http.StatusOK)
|
||||
requireStatusCode(t, http.StatusOK, status, raw)
|
||||
@@ -1130,7 +1137,13 @@ func (a apiClient) ConvertPrometheusGetRuleGroupRules(t *testing.T, namespaceTit
|
||||
|
||||
func (a apiClient) ConvertPrometheusGetNamespaceRules(t *testing.T, namespaceTitle string) map[string][]apimodels.PrometheusRuleGroup {
|
||||
t.Helper()
|
||||
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/api/convert/prometheus/config/v1/rules/%s", a.url, namespaceTitle), nil)
|
||||
|
||||
path := "%s/api/convert/prometheus/config/v1/rules/%s"
|
||||
if a.prometheusConversionUseLokiPaths {
|
||||
path = "%s/api/convert/api/prom/rules/%s"
|
||||
}
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf(path, a.url, namespaceTitle), nil)
|
||||
require.NoError(t, err)
|
||||
ns, status, raw := sendRequestYAML[map[string][]apimodels.PrometheusRuleGroup](t, req, http.StatusOK)
|
||||
requireStatusCode(t, http.StatusOK, status, raw)
|
||||
@@ -1139,7 +1152,13 @@ func (a apiClient) ConvertPrometheusGetNamespaceRules(t *testing.T, namespaceTit
|
||||
|
||||
func (a apiClient) ConvertPrometheusGetAllRules(t *testing.T) map[string][]apimodels.PrometheusRuleGroup {
|
||||
t.Helper()
|
||||
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/api/convert/prometheus/config/v1/rules", a.url), nil)
|
||||
|
||||
path := "%s/api/convert/prometheus/config/v1/rules"
|
||||
if a.prometheusConversionUseLokiPaths {
|
||||
path = "%s/api/convert/api/prom/rules"
|
||||
}
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf(path, a.url), nil)
|
||||
require.NoError(t, err)
|
||||
result, status, raw := sendRequestYAML[map[string][]apimodels.PrometheusRuleGroup](t, req, http.StatusOK)
|
||||
requireStatusCode(t, http.StatusOK, status, raw)
|
||||
@@ -1148,7 +1167,13 @@ func (a apiClient) ConvertPrometheusGetAllRules(t *testing.T) map[string][]apimo
|
||||
|
||||
func (a apiClient) ConvertPrometheusDeleteRuleGroup(t *testing.T, namespaceTitle, groupName string) {
|
||||
t.Helper()
|
||||
req, err := http.NewRequest(http.MethodDelete, fmt.Sprintf("%s/api/convert/prometheus/config/v1/rules/%s/%s", a.url, namespaceTitle, groupName), nil)
|
||||
|
||||
path := "%s/api/convert/prometheus/config/v1/rules/%s/%s"
|
||||
if a.prometheusConversionUseLokiPaths {
|
||||
path = "%s/api/convert/api/prom/rules/%s/%s"
|
||||
}
|
||||
|
||||
req, err := http.NewRequest(http.MethodDelete, fmt.Sprintf(path, a.url, namespaceTitle, groupName), nil)
|
||||
require.NoError(t, err)
|
||||
_, status, raw := sendRequestJSON[apimodels.ConvertPrometheusResponse](t, req, http.StatusAccepted)
|
||||
requireStatusCode(t, http.StatusAccepted, status, raw)
|
||||
@@ -1156,7 +1181,13 @@ func (a apiClient) ConvertPrometheusDeleteRuleGroup(t *testing.T, namespaceTitle
|
||||
|
||||
func (a apiClient) ConvertPrometheusDeleteNamespace(t *testing.T, namespaceTitle string) {
|
||||
t.Helper()
|
||||
req, err := http.NewRequest(http.MethodDelete, fmt.Sprintf("%s/api/convert/prometheus/config/v1/rules/%s", a.url, namespaceTitle), nil)
|
||||
|
||||
path := "%s/api/convert/prometheus/config/v1/rules/%s"
|
||||
if a.prometheusConversionUseLokiPaths {
|
||||
path = "%s/api/convert/api/prom/rules/%s"
|
||||
}
|
||||
|
||||
req, err := http.NewRequest(http.MethodDelete, fmt.Sprintf(path, a.url, namespaceTitle), nil)
|
||||
require.NoError(t, err)
|
||||
_, status, raw := sendRequestJSON[apimodels.ConvertPrometheusResponse](t, req, http.StatusAccepted)
|
||||
requireStatusCode(t, http.StatusAccepted, status, raw)
|
||||
|
||||
Reference in New Issue
Block a user