NgAlerting: loki & cortex have different prom & ruler endpoint prefixes (#32344)

This commit is contained in:
Domas 2021-03-29 08:55:09 +03:00 committed by GitHub
parent feaaa32ffd
commit 0779dab0de
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 80 additions and 8 deletions

View File

@ -16,7 +16,10 @@ import (
"github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/models"
) )
const legacyRulerPrefix = "/api/prom/rules" var dsTypeToRulerPrefix = map[string]string{
"prometheus": "/rules",
"loki": "/api/prom/rules",
}
type LotexRuler struct { type LotexRuler struct {
log log.Logger log log.Logger
@ -31,13 +34,17 @@ func NewLotexRuler(proxy *AlertingProxy, log log.Logger) *LotexRuler {
} }
func (r *LotexRuler) RouteDeleteNamespaceRulesConfig(ctx *models.ReqContext) response.Response { func (r *LotexRuler) RouteDeleteNamespaceRulesConfig(ctx *models.ReqContext) response.Response {
legacyRulerPrefix, err := r.getPrefix(ctx)
if err != nil {
return response.Error(500, err.Error(), nil)
}
return r.withReq( return r.withReq(
ctx, ctx,
&http.Request{ &http.Request{
Method: "DELETE", Method: "DELETE",
URL: withPath( URL: withPath(
*ctx.Req.URL, *ctx.Req.URL,
fmt.Sprintf("/api/prom/rules/%s", ctx.Params("Namespace")), fmt.Sprintf("%s/%s", legacyRulerPrefix, ctx.Params("Namespace")),
), ),
}, },
messageExtractor, messageExtractor,
@ -45,6 +52,10 @@ func (r *LotexRuler) RouteDeleteNamespaceRulesConfig(ctx *models.ReqContext) res
} }
func (r *LotexRuler) RouteDeleteRuleGroupConfig(ctx *models.ReqContext) response.Response { func (r *LotexRuler) RouteDeleteRuleGroupConfig(ctx *models.ReqContext) response.Response {
legacyRulerPrefix, err := r.getPrefix(ctx)
if err != nil {
return response.Error(500, err.Error(), nil)
}
return r.withReq( return r.withReq(
ctx, ctx,
&http.Request{ &http.Request{
@ -64,6 +75,10 @@ func (r *LotexRuler) RouteDeleteRuleGroupConfig(ctx *models.ReqContext) response
} }
func (r *LotexRuler) RouteGetNamespaceRulesConfig(ctx *models.ReqContext) response.Response { func (r *LotexRuler) RouteGetNamespaceRulesConfig(ctx *models.ReqContext) response.Response {
legacyRulerPrefix, err := r.getPrefix(ctx)
if err != nil {
return response.Error(500, err.Error(), nil)
}
return r.withReq( return r.withReq(
ctx, &http.Request{ ctx, &http.Request{
URL: withPath( URL: withPath(
@ -80,6 +95,10 @@ func (r *LotexRuler) RouteGetNamespaceRulesConfig(ctx *models.ReqContext) respon
} }
func (r *LotexRuler) RouteGetRulegGroupConfig(ctx *models.ReqContext) response.Response { func (r *LotexRuler) RouteGetRulegGroupConfig(ctx *models.ReqContext) response.Response {
legacyRulerPrefix, err := r.getPrefix(ctx)
if err != nil {
return response.Error(500, err.Error(), nil)
}
return r.withReq( return r.withReq(
ctx, ctx,
&http.Request{ &http.Request{
@ -98,6 +117,10 @@ func (r *LotexRuler) RouteGetRulegGroupConfig(ctx *models.ReqContext) response.R
} }
func (r *LotexRuler) RouteGetRulesConfig(ctx *models.ReqContext) response.Response { func (r *LotexRuler) RouteGetRulesConfig(ctx *models.ReqContext) response.Response {
legacyRulerPrefix, err := r.getPrefix(ctx)
if err != nil {
return response.Error(500, err.Error(), nil)
}
return r.withReq( return r.withReq(
ctx, ctx,
&http.Request{ &http.Request{
@ -111,6 +134,10 @@ func (r *LotexRuler) RouteGetRulesConfig(ctx *models.ReqContext) response.Respon
} }
func (r *LotexRuler) RoutePostNameRulesConfig(ctx *models.ReqContext, conf apimodels.RuleGroupConfig) response.Response { func (r *LotexRuler) RoutePostNameRulesConfig(ctx *models.ReqContext, conf apimodels.RuleGroupConfig) response.Response {
legacyRulerPrefix, err := r.getPrefix(ctx)
if err != nil {
return response.Error(500, err.Error(), nil)
}
yml, err := yaml.Marshal(conf) yml, err := yaml.Marshal(conf)
if err != nil { if err != nil {
return response.Error(500, "Failed marshal rule group", err) return response.Error(500, "Failed marshal rule group", err)
@ -129,6 +156,18 @@ func (r *LotexRuler) RoutePostNameRulesConfig(ctx *models.ReqContext, conf apimo
return r.withReq(ctx, req, jsonExtractor(nil)) return r.withReq(ctx, req, jsonExtractor(nil))
} }
func (r *LotexRuler) getPrefix(ctx *models.ReqContext) (string, error) {
ds, err := r.DataProxy.DatasourceCache.GetDatasource(ctx.ParamsInt64("Recipient"), ctx.SignedInUser, ctx.SkipCache)
if err != nil {
return "", err
}
prefix, ok := dsTypeToRulerPrefix[ds.Type]
if !ok {
return "", fmt.Errorf("unexpected datasource type. expecting loki or prometheus")
}
return prefix, nil
}
func withPath(u url.URL, newPath string) *url.URL { func withPath(u url.URL, newPath string) *url.URL {
// TODO: handle path escaping // TODO: handle path escaping
u.Path = newPath u.Path = newPath

View File

@ -1,6 +1,7 @@
package api package api
import ( import (
"fmt"
"net/http" "net/http"
apimodels "github.com/grafana/alerting-api/pkg/api" apimodels "github.com/grafana/alerting-api/pkg/api"
@ -9,10 +10,20 @@ import (
"github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/models"
) )
const ( type promEndpoints struct {
promRulesPath = "/prometheus/api/v1/rules" rules, alerts string
promAlertsPath = "/prometheus/api/v1/alerts" }
)
var dsTypeToLotexRoutes = map[string]promEndpoints{
"prometheus": {
rules: "/api/v1/rules",
alerts: "/api/v1/alerts",
},
"loki": {
rules: "/prometheus/api/v1/rules",
alerts: "/prometheus/api/v1/alerts",
},
}
type LotexProm struct { type LotexProm struct {
log log.Logger log log.Logger
@ -27,11 +38,16 @@ func NewLotexProm(proxy *AlertingProxy, log log.Logger) *LotexProm {
} }
func (p *LotexProm) RouteGetAlertStatuses(ctx *models.ReqContext) response.Response { func (p *LotexProm) RouteGetAlertStatuses(ctx *models.ReqContext) response.Response {
endpoints, err := p.getEndpoints(ctx)
if err != nil {
return response.Error(500, err.Error(), nil)
}
return p.withReq( return p.withReq(
ctx, &http.Request{ ctx, &http.Request{
URL: withPath( URL: withPath(
*ctx.Req.URL, *ctx.Req.URL,
promAlertsPath, endpoints.alerts,
), ),
}, },
jsonExtractor(&apimodels.AlertResponse{}), jsonExtractor(&apimodels.AlertResponse{}),
@ -39,13 +55,30 @@ func (p *LotexProm) RouteGetAlertStatuses(ctx *models.ReqContext) response.Respo
} }
func (p *LotexProm) RouteGetRuleStatuses(ctx *models.ReqContext) response.Response { func (p *LotexProm) RouteGetRuleStatuses(ctx *models.ReqContext) response.Response {
endpoints, err := p.getEndpoints(ctx)
if err != nil {
return response.Error(500, err.Error(), nil)
}
return p.withReq( return p.withReq(
ctx, &http.Request{ ctx, &http.Request{
URL: withPath( URL: withPath(
*ctx.Req.URL, *ctx.Req.URL,
promRulesPath, endpoints.rules,
), ),
}, },
jsonExtractor(&apimodels.RuleResponse{}), jsonExtractor(&apimodels.RuleResponse{}),
) )
} }
func (p *LotexProm) getEndpoints(ctx *models.ReqContext) (*promEndpoints, error) {
ds, err := p.DataProxy.DatasourceCache.GetDatasource(ctx.ParamsInt64("Recipient"), ctx.SignedInUser, ctx.SkipCache)
if err != nil {
return nil, err
}
routes, ok := dsTypeToLotexRoutes[ds.Type]
if !ok {
return nil, fmt.Errorf("unexpected datasource type. expecting loki or prometheus")
}
return &routes, nil
}