Files
grafana/pkg/services/ngalert/api/lotex_prom.go
Kevin Yu fd6fd91115 Prometheus: Add support for cloud partners Prometheus data sources (#103482)
* wip

* Add prom flavor support for data source variables and export/import dashboards (#103321)

* add dashboard and data source var selection

* use match plugin id instead

* use updated matchpluginid

* formatting

* cleanup

* regex anchor

* update error msg

* Alerting: Clean up prometheus-flavored types and functions (#103703)

* clean up types and utility functions for dealing with
prometheus-flavored data sources

* Refactor alerting datasource types to use constants as source of truth

* Alerting: Clean up prometheus-flavored types and functions on the bac… (#103716)

Alerting: Clean up prometheus-flavored types and functions on the backend

* add matchPluginId tests

* Update matchPluginId func to bidirectional (#103746)

* update matchpluginid func to bidirectional

* lint

* formatting

* use actual isSupportedExternalRulesSourceType in test

* add tests in datasource_srv

* betterer

* remove type assertion

* remove unnecessary case

* use satisifies to not have to convert tuple to an array of string

* add prometheus_flavor test

---------

Co-authored-by: Andrew Hackmann <5140848+bossinc@users.noreply.github.com>
Co-authored-by: Gilles De Mey <gilles.de.mey@gmail.com>
Co-authored-by: Alexander Akhmetov <me@alx.cx>
2025-04-10 12:49:11 -07:00

107 lines
2.3 KiB
Go

package api
import (
"fmt"
"net/http"
"github.com/grafana/grafana/pkg/api/response"
"github.com/grafana/grafana/pkg/infra/log"
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
"github.com/grafana/grafana/pkg/services/datasources"
apimodels "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
"github.com/grafana/grafana/pkg/web"
)
type promEndpoints struct {
rules, alerts string
}
var (
prometheusEndpoints = promEndpoints{
rules: "/api/v1/rules",
alerts: "/api/v1/alerts",
}
lokiEndpoints = promEndpoints{
rules: "/prometheus/api/v1/rules",
alerts: "/prometheus/api/v1/alerts",
}
)
type LotexProm struct {
log log.Logger
*AlertingProxy
}
func NewLotexProm(proxy *AlertingProxy, log log.Logger) *LotexProm {
return &LotexProm{
log: log,
AlertingProxy: proxy,
}
}
func (p *LotexProm) RouteGetAlertStatuses(ctx *contextmodel.ReqContext) response.Response {
endpoints, err := p.getEndpoints(ctx)
if err != nil {
return ErrResp(http.StatusInternalServerError, err, "")
}
return p.withReq(
ctx,
http.MethodGet,
withPath(
*ctx.Req.URL,
endpoints.alerts,
),
nil,
jsonExtractor(&apimodels.AlertResponse{}),
nil,
)
}
func (p *LotexProm) RouteGetRuleStatuses(ctx *contextmodel.ReqContext) response.Response {
endpoints, err := p.getEndpoints(ctx)
if err != nil {
return ErrResp(http.StatusInternalServerError, err, "")
}
return p.withReq(
ctx,
http.MethodGet,
withPath(
*ctx.Req.URL,
endpoints.rules,
),
nil,
jsonExtractor(&apimodels.RuleResponse{}),
nil,
)
}
func (p *LotexProm) getEndpoints(ctx *contextmodel.ReqContext) (*promEndpoints, error) {
datasourceUID := web.Params(ctx.Req)[":DatasourceUID"]
if datasourceUID == "" {
return nil, fmt.Errorf("datasource UID is invalid")
}
ds, err := p.DataProxy.DataSourceCache.GetDatasourceByUID(ctx.Req.Context(), datasourceUID, ctx.SignedInUser, ctx.SkipDSCache)
if err != nil {
return nil, err
}
if ds.URL == "" {
return nil, fmt.Errorf("URL for this data source is empty")
}
var routes promEndpoints
switch {
case isPrometheusCompatible(ds.Type):
routes = prometheusEndpoints
case ds.Type == datasources.DS_LOKI:
routes = lokiEndpoints
default:
return nil, unexpectedDatasourceTypeError(ds.Type, "loki, prometheus, amazon prometheus, azure prometheus")
}
return &routes, nil
}