diff --git a/pkg/api/dataproxy.go b/pkg/api/dataproxy.go index af006072019..220f3f31b7a 100644 --- a/pkg/api/dataproxy.go +++ b/pkg/api/dataproxy.go @@ -7,5 +7,5 @@ func (hs *HTTPServer) ProxyDataSourceRequest(c *models.ReqContext) { } func (hs *HTTPServer) ProxyDataSourceRequestWithUID(c *models.ReqContext) { - hs.DataProxy.ProxyDatasourceRequestWithUID(c) + hs.DataProxy.ProxyDatasourceRequestWithUID(c, "") } diff --git a/pkg/services/datasourceproxy/datasourceproxy.go b/pkg/services/datasourceproxy/datasourceproxy.go index c40c4360e06..9a8a003b2a7 100644 --- a/pkg/services/datasourceproxy/datasourceproxy.go +++ b/pkg/services/datasourceproxy/datasourceproxy.go @@ -60,10 +60,13 @@ func (p *DataSourceProxyService) ProxyDataSourceRequest(c *models.ReqContext) { p.ProxyDatasourceRequestWithID(c, id) } -func (p *DataSourceProxyService) ProxyDatasourceRequestWithUID(c *models.ReqContext) { +func (p *DataSourceProxyService) ProxyDatasourceRequestWithUID(c *models.ReqContext, dsUID string) { c.TimeRequest(metrics.MDataSourceProxyReqTimer) - dsUID := web.Params(c.Req)[":uid"] + if dsUID == "" { // if datasource UID is not provided, fetch it from the uid path parameter + dsUID = web.Params(c.Req)[":uid"] + } + if !util.IsValidShortUID(dsUID) { c.JsonApiErr(http.StatusBadRequest, "UID is invalid", nil) return diff --git a/pkg/services/ngalert/api/authorization.go b/pkg/services/ngalert/api/authorization.go index 7d9d1a0fe81..560c10ca168 100644 --- a/pkg/services/ngalert/api/authorization.go +++ b/pkg/services/ngalert/api/authorization.go @@ -122,22 +122,22 @@ func (api *API) authorize(method, path string) web.Handler { eval = ac.EvalPermission(ac.ActionAlertingInstanceRead) // Silences. External AM. - case http.MethodDelete + "/api/alertmanager/{DatasourceID}/api/v2/silence/{SilenceId}": - eval = ac.EvalPermission(ac.ActionAlertingInstancesExternalWrite, datasources.ScopeProvider.GetResourceScope(ac.Parameter(":DatasourceID"))) - case http.MethodPost + "/api/alertmanager/{DatasourceID}/api/v2/silences": - eval = ac.EvalPermission(ac.ActionAlertingInstancesExternalWrite, datasources.ScopeProvider.GetResourceScope(ac.Parameter(":DatasourceID"))) - case http.MethodGet + "/api/alertmanager/{DatasourceID}/api/v2/silence/{SilenceId}": - eval = ac.EvalPermission(ac.ActionAlertingInstancesExternalRead, datasources.ScopeProvider.GetResourceScope(ac.Parameter(":DatasourceID"))) - case http.MethodGet + "/api/alertmanager/{DatasourceID}/api/v2/silences": - eval = ac.EvalPermission(ac.ActionAlertingInstancesExternalRead, datasources.ScopeProvider.GetResourceScope(ac.Parameter(":DatasourceID"))) + case http.MethodDelete + "/api/alertmanager/{DatasourceUID}/api/v2/silence/{SilenceId}": + eval = ac.EvalPermission(ac.ActionAlertingInstancesExternalWrite, datasources.ScopeProvider.GetResourceScopeUID(ac.Parameter(":DatasourceUID"))) + case http.MethodPost + "/api/alertmanager/{DatasourceUID}/api/v2/silences": + eval = ac.EvalPermission(ac.ActionAlertingInstancesExternalWrite, datasources.ScopeProvider.GetResourceScopeUID(ac.Parameter(":DatasourceUID"))) + case http.MethodGet + "/api/alertmanager/{DatasourceUID}/api/v2/silence/{SilenceId}": + eval = ac.EvalPermission(ac.ActionAlertingInstancesExternalRead, datasources.ScopeProvider.GetResourceScopeUID(ac.Parameter(":DatasourceUID"))) + case http.MethodGet + "/api/alertmanager/{DatasourceUID}/api/v2/silences": + eval = ac.EvalPermission(ac.ActionAlertingInstancesExternalRead, datasources.ScopeProvider.GetResourceScopeUID(ac.Parameter(":DatasourceUID"))) // Alert instances. External AM. - case http.MethodGet + "/api/alertmanager/{DatasourceID}/api/v2/alerts/groups": - eval = ac.EvalPermission(ac.ActionAlertingInstancesExternalRead, datasources.ScopeProvider.GetResourceScope(ac.Parameter(":DatasourceID"))) - case http.MethodGet + "/api/alertmanager/{DatasourceID}/api/v2/alerts": - eval = ac.EvalPermission(ac.ActionAlertingInstancesExternalRead, datasources.ScopeProvider.GetResourceScope(ac.Parameter(":DatasourceID"))) - case http.MethodPost + "/api/alertmanager/{DatasourceID}/api/v2/alerts": - eval = ac.EvalPermission(ac.ActionAlertingInstancesExternalWrite, datasources.ScopeProvider.GetResourceScope(ac.Parameter(":DatasourceID"))) + case http.MethodGet + "/api/alertmanager/{DatasourceUID}/api/v2/alerts/groups": + eval = ac.EvalPermission(ac.ActionAlertingInstancesExternalRead, datasources.ScopeProvider.GetResourceScopeUID(ac.Parameter(":DatasourceUID"))) + case http.MethodGet + "/api/alertmanager/{DatasourceUID}/api/v2/alerts": + eval = ac.EvalPermission(ac.ActionAlertingInstancesExternalRead, datasources.ScopeProvider.GetResourceScopeUID(ac.Parameter(":DatasourceUID"))) + case http.MethodPost + "/api/alertmanager/{DatasourceUID}/api/v2/alerts": + eval = ac.EvalPermission(ac.ActionAlertingInstancesExternalWrite, datasources.ScopeProvider.GetResourceScopeUID(ac.Parameter(":DatasourceUID"))) // Prometheus-compatible Paths case http.MethodGet + "/api/prometheus/{DatasourceID}/api/v1/alerts": @@ -161,16 +161,16 @@ func (api *API) authorize(method, path string) web.Handler { eval = ac.EvalPermission(ac.ActionAlertingNotificationsRead) // External Alertmanager Paths - case http.MethodDelete + "/api/alertmanager/{DatasourceID}/config/api/v1/alerts": - eval = ac.EvalPermission(ac.ActionAlertingNotificationsDelete, datasources.ScopeProvider.GetResourceScope(ac.Parameter(":DatasourceID"))) - case http.MethodGet + "/api/alertmanager/{DatasourceID}/api/v2/status": - eval = ac.EvalPermission(ac.ActionAlertingNotificationsExternalRead, datasources.ScopeProvider.GetResourceScope(ac.Parameter(":DatasourceID"))) - case http.MethodGet + "/api/alertmanager/{DatasourceID}/config/api/v1/alerts": - eval = ac.EvalPermission(ac.ActionAlertingNotificationsExternalRead, datasources.ScopeProvider.GetResourceScope(ac.Parameter(":DatasourceID"))) - case http.MethodPost + "/api/alertmanager/{DatasourceID}/config/api/v1/alerts": + case http.MethodDelete + "/api/alertmanager/{DatasourceUID}/config/api/v1/alerts": + eval = ac.EvalPermission(ac.ActionAlertingNotificationsDelete, datasources.ScopeProvider.GetResourceScopeUID(ac.Parameter(":DatasourceUID"))) + case http.MethodGet + "/api/alertmanager/{DatasourceUID}/api/v2/status": + eval = ac.EvalPermission(ac.ActionAlertingNotificationsExternalRead, datasources.ScopeProvider.GetResourceScopeUID(ac.Parameter(":DatasourceUID"))) + case http.MethodGet + "/api/alertmanager/{DatasourceUID}/config/api/v1/alerts": + eval = ac.EvalPermission(ac.ActionAlertingNotificationsExternalRead, datasources.ScopeProvider.GetResourceScopeUID(ac.Parameter(":DatasourceUID"))) + case http.MethodPost + "/api/alertmanager/{DatasourceUID}/config/api/v1/alerts": eval = ac.EvalPermission(ac.ActionAlertingNotificationsExternalWrite, datasources.ScopeProvider.GetResourceScope(ac.Parameter(":DatasourceID"))) - case http.MethodPost + "/api/alertmanager/{DatasourceID}/config/api/v1/receivers/test": - eval = ac.EvalPermission(ac.ActionAlertingNotificationsExternalRead, datasources.ScopeProvider.GetResourceScope(ac.Parameter(":DatasourceID"))) + case http.MethodPost + "/api/alertmanager/{DatasourceUID}/config/api/v1/receivers/test": + eval = ac.EvalPermission(ac.ActionAlertingNotificationsExternalRead, datasources.ScopeProvider.GetResourceScopeUID(ac.Parameter(":DatasourceUID"))) // Raw Alertmanager Config Paths case http.MethodDelete + "/api/v1/ngalert/admin_config", diff --git a/pkg/services/ngalert/api/forked_am.go b/pkg/services/ngalert/api/forked_am.go index 5201d8f315e..069a0bce6c5 100644 --- a/pkg/services/ngalert/api/forked_am.go +++ b/pkg/services/ngalert/api/forked_am.go @@ -25,7 +25,7 @@ func NewForkedAM(datasourceCache datasources.CacheService, proxy *LotexAM, grafa } func (f *ForkedAlertmanagerApi) getService(ctx *models.ReqContext) (*LotexAM, error) { - t, err := backendType(ctx, f.DatasourceCache) + t, err := backendTypeByUID(ctx, f.DatasourceCache) if err != nil { return nil, err } @@ -125,7 +125,7 @@ func (f *ForkedAlertmanagerApi) forkRoutePostAlertingConfig(ctx *models.ReqConte return ErrResp(400, err, "") } - b, err := backendType(ctx, f.DatasourceCache) + b, err := backendTypeByUID(ctx, f.DatasourceCache) if err != nil { return ErrResp(400, err, "") } diff --git a/pkg/services/ngalert/api/generated_base_api_alertmanager.go b/pkg/services/ngalert/api/generated_base_api_alertmanager.go index e6539e2183e..5b744e66038 100644 --- a/pkg/services/ngalert/api/generated_base_api_alertmanager.go +++ b/pkg/services/ngalert/api/generated_base_api_alertmanager.go @@ -187,21 +187,21 @@ func (api *API) RegisterAlertmanagerApiEndpoints(srv AlertmanagerApiForkingServi ), ) group.Post( - toMacaronPath("/api/alertmanager/{DatasourceID}/api/v2/silences"), - api.authorize(http.MethodPost, "/api/alertmanager/{DatasourceID}/api/v2/silences"), + toMacaronPath("/api/alertmanager/{DatasourceUID}/api/v2/silences"), + api.authorize(http.MethodPost, "/api/alertmanager/{DatasourceUID}/api/v2/silences"), metrics.Instrument( http.MethodPost, - "/api/alertmanager/{DatasourceID}/api/v2/silences", + "/api/alertmanager/{DatasourceUID}/api/v2/silences", srv.RouteCreateSilence, m, ), ) group.Delete( - toMacaronPath("/api/alertmanager/{DatasourceID}/config/api/v1/alerts"), - api.authorize(http.MethodDelete, "/api/alertmanager/{DatasourceID}/config/api/v1/alerts"), + toMacaronPath("/api/alertmanager/{DatasourceUID}/config/api/v1/alerts"), + api.authorize(http.MethodDelete, "/api/alertmanager/{DatasourceUID}/config/api/v1/alerts"), metrics.Instrument( http.MethodDelete, - "/api/alertmanager/{DatasourceID}/config/api/v1/alerts", + "/api/alertmanager/{DatasourceUID}/config/api/v1/alerts", srv.RouteDeleteAlertingConfig, m, ), @@ -227,51 +227,51 @@ func (api *API) RegisterAlertmanagerApiEndpoints(srv AlertmanagerApiForkingServi ), ) group.Delete( - toMacaronPath("/api/alertmanager/{DatasourceID}/api/v2/silence/{SilenceId}"), - api.authorize(http.MethodDelete, "/api/alertmanager/{DatasourceID}/api/v2/silence/{SilenceId}"), + toMacaronPath("/api/alertmanager/{DatasourceUID}/api/v2/silence/{SilenceId}"), + api.authorize(http.MethodDelete, "/api/alertmanager/{DatasourceUID}/api/v2/silence/{SilenceId}"), metrics.Instrument( http.MethodDelete, - "/api/alertmanager/{DatasourceID}/api/v2/silence/{SilenceId}", + "/api/alertmanager/{DatasourceUID}/api/v2/silence/{SilenceId}", srv.RouteDeleteSilence, m, ), ) group.Get( - toMacaronPath("/api/alertmanager/{DatasourceID}/api/v2/alerts/groups"), - api.authorize(http.MethodGet, "/api/alertmanager/{DatasourceID}/api/v2/alerts/groups"), + toMacaronPath("/api/alertmanager/{DatasourceUID}/api/v2/alerts/groups"), + api.authorize(http.MethodGet, "/api/alertmanager/{DatasourceUID}/api/v2/alerts/groups"), metrics.Instrument( http.MethodGet, - "/api/alertmanager/{DatasourceID}/api/v2/alerts/groups", + "/api/alertmanager/{DatasourceUID}/api/v2/alerts/groups", srv.RouteGetAMAlertGroups, m, ), ) group.Get( - toMacaronPath("/api/alertmanager/{DatasourceID}/api/v2/alerts"), - api.authorize(http.MethodGet, "/api/alertmanager/{DatasourceID}/api/v2/alerts"), + toMacaronPath("/api/alertmanager/{DatasourceUID}/api/v2/alerts"), + api.authorize(http.MethodGet, "/api/alertmanager/{DatasourceUID}/api/v2/alerts"), metrics.Instrument( http.MethodGet, - "/api/alertmanager/{DatasourceID}/api/v2/alerts", + "/api/alertmanager/{DatasourceUID}/api/v2/alerts", srv.RouteGetAMAlerts, m, ), ) group.Get( - toMacaronPath("/api/alertmanager/{DatasourceID}/api/v2/status"), - api.authorize(http.MethodGet, "/api/alertmanager/{DatasourceID}/api/v2/status"), + toMacaronPath("/api/alertmanager/{DatasourceUID}/api/v2/status"), + api.authorize(http.MethodGet, "/api/alertmanager/{DatasourceUID}/api/v2/status"), metrics.Instrument( http.MethodGet, - "/api/alertmanager/{DatasourceID}/api/v2/status", + "/api/alertmanager/{DatasourceUID}/api/v2/status", srv.RouteGetAMStatus, m, ), ) group.Get( - toMacaronPath("/api/alertmanager/{DatasourceID}/config/api/v1/alerts"), - api.authorize(http.MethodGet, "/api/alertmanager/{DatasourceID}/config/api/v1/alerts"), + toMacaronPath("/api/alertmanager/{DatasourceUID}/config/api/v1/alerts"), + api.authorize(http.MethodGet, "/api/alertmanager/{DatasourceUID}/config/api/v1/alerts"), metrics.Instrument( http.MethodGet, - "/api/alertmanager/{DatasourceID}/config/api/v1/alerts", + "/api/alertmanager/{DatasourceUID}/config/api/v1/alerts", srv.RouteGetAlertingConfig, m, ), @@ -337,41 +337,41 @@ func (api *API) RegisterAlertmanagerApiEndpoints(srv AlertmanagerApiForkingServi ), ) group.Get( - toMacaronPath("/api/alertmanager/{DatasourceID}/api/v2/silence/{SilenceId}"), - api.authorize(http.MethodGet, "/api/alertmanager/{DatasourceID}/api/v2/silence/{SilenceId}"), + toMacaronPath("/api/alertmanager/{DatasourceUID}/api/v2/silence/{SilenceId}"), + api.authorize(http.MethodGet, "/api/alertmanager/{DatasourceUID}/api/v2/silence/{SilenceId}"), metrics.Instrument( http.MethodGet, - "/api/alertmanager/{DatasourceID}/api/v2/silence/{SilenceId}", + "/api/alertmanager/{DatasourceUID}/api/v2/silence/{SilenceId}", srv.RouteGetSilence, m, ), ) group.Get( - toMacaronPath("/api/alertmanager/{DatasourceID}/api/v2/silences"), - api.authorize(http.MethodGet, "/api/alertmanager/{DatasourceID}/api/v2/silences"), + toMacaronPath("/api/alertmanager/{DatasourceUID}/api/v2/silences"), + api.authorize(http.MethodGet, "/api/alertmanager/{DatasourceUID}/api/v2/silences"), metrics.Instrument( http.MethodGet, - "/api/alertmanager/{DatasourceID}/api/v2/silences", + "/api/alertmanager/{DatasourceUID}/api/v2/silences", srv.RouteGetSilences, m, ), ) group.Post( - toMacaronPath("/api/alertmanager/{DatasourceID}/api/v2/alerts"), - api.authorize(http.MethodPost, "/api/alertmanager/{DatasourceID}/api/v2/alerts"), + toMacaronPath("/api/alertmanager/{DatasourceUID}/api/v2/alerts"), + api.authorize(http.MethodPost, "/api/alertmanager/{DatasourceUID}/api/v2/alerts"), metrics.Instrument( http.MethodPost, - "/api/alertmanager/{DatasourceID}/api/v2/alerts", + "/api/alertmanager/{DatasourceUID}/api/v2/alerts", srv.RoutePostAMAlerts, m, ), ) group.Post( - toMacaronPath("/api/alertmanager/{DatasourceID}/config/api/v1/alerts"), - api.authorize(http.MethodPost, "/api/alertmanager/{DatasourceID}/config/api/v1/alerts"), + toMacaronPath("/api/alertmanager/{DatasourceUID}/config/api/v1/alerts"), + api.authorize(http.MethodPost, "/api/alertmanager/{DatasourceUID}/config/api/v1/alerts"), metrics.Instrument( http.MethodPost, - "/api/alertmanager/{DatasourceID}/config/api/v1/alerts", + "/api/alertmanager/{DatasourceUID}/config/api/v1/alerts", srv.RoutePostAlertingConfig, m, ), @@ -407,11 +407,11 @@ func (api *API) RegisterAlertmanagerApiEndpoints(srv AlertmanagerApiForkingServi ), ) group.Post( - toMacaronPath("/api/alertmanager/{DatasourceID}/config/api/v1/receivers/test"), - api.authorize(http.MethodPost, "/api/alertmanager/{DatasourceID}/config/api/v1/receivers/test"), + toMacaronPath("/api/alertmanager/{DatasourceUID}/config/api/v1/receivers/test"), + api.authorize(http.MethodPost, "/api/alertmanager/{DatasourceUID}/config/api/v1/receivers/test"), metrics.Instrument( http.MethodPost, - "/api/alertmanager/{DatasourceID}/config/api/v1/receivers/test", + "/api/alertmanager/{DatasourceUID}/config/api/v1/receivers/test", srv.RoutePostTestReceivers, m, ), diff --git a/pkg/services/ngalert/api/lotex_am.go b/pkg/services/ngalert/api/lotex_am.go index 2eb5ff18000..d78eb536ba5 100644 --- a/pkg/services/ngalert/api/lotex_am.go +++ b/pkg/services/ngalert/api/lotex_am.go @@ -7,7 +7,6 @@ import ( "fmt" "io" "net/http" - "strconv" "github.com/grafana/grafana/pkg/api/response" "github.com/grafana/grafana/pkg/infra/log" @@ -60,12 +59,12 @@ func (am *LotexAM) withAMReq( extractor func(*response.NormalResponse) (interface{}, error), headers map[string]string, ) response.Response { - datasourceID, err := strconv.ParseInt(web.Params(ctx.Req)[":DatasourceID"], 10, 64) - if err != nil { - return response.Error(http.StatusBadRequest, "DatasourceID is invalid", err) + datasourceUID := web.Params(ctx.Req)[":DatasourceUID"] + if datasourceUID == "" { + return response.Error(http.StatusBadRequest, "DatasourceUID is invalid", nil) } - ds, err := am.DataProxy.DataSourceCache.GetDatasource(ctx.Req.Context(), datasourceID, ctx.SignedInUser, ctx.SkipCache) + ds, err := am.DataProxy.DataSourceCache.GetDatasourceByUID(ctx.Req.Context(), datasourceUID, ctx.SignedInUser, ctx.SkipCache) if err != nil { if errors.Is(err, models.ErrDataSourceAccessDenied) { return ErrResp(http.StatusForbidden, err, "Access denied to datasource") diff --git a/pkg/services/ngalert/api/test-data/am-alertmanager-recipient.http b/pkg/services/ngalert/api/test-data/am-alertmanager-recipient.http index 6fc614fa31d..9452e77bf9d 100644 --- a/pkg/services/ngalert/api/test-data/am-alertmanager-recipient.http +++ b/pkg/services/ngalert/api/test-data/am-alertmanager-recipient.http @@ -1,8 +1,8 @@ -@alertManagerDatasourceID = 36 +@alertManagerDatasourceUID = Y4t6ca_Mz ### # create AM configuration -POST http://admin:admin@localhost:3000/api/alertmanager/{{alertManagerDatasourceID}}/config/api/v1/alerts +POST http://admin:admin@localhost:3000/api/alertmanager/{{alertManagerDatasourceUID}}/config/api/v1/alerts content-type: application/json { @@ -62,16 +62,16 @@ content-type: application/json ### # get latest AM configuration -GET http://admin:admin@localhost:3000/api/alertmanager/{{alertManagerDatasourceID}}/config/api/v1/alerts +GET http://admin:admin@localhost:3000/api/alertmanager/{{alertManagerDatasourceUID}}/config/api/v1/alerts content-type: application/json ### # delete AM configuration -DELETE http://admin:admin@localhost:3000/api/alertmanager/{{alertManagerDatasourceID}}/config/api/v1/alerts +DELETE http://admin:admin@localhost:3000/api/alertmanager/{{alertManagerDatasourceUID}}/config/api/v1/alerts ### # create AM alerts -POST http://admin:admin@localhost:3000/api/alertmanager/{{alertManagerDatasourceID}}/api/v2/alerts +POST http://admin:admin@localhost:3000/api/alertmanager/{{alertManagerDatasourceUID}}/api/v2/alerts content-type: application/json [ @@ -94,23 +94,23 @@ content-type: application/json ### # get AM alerts -GET http://admin:admin@localhost:3000/api/alertmanager/{{alertManagerDatasourceID}}/api/v2/alerts +GET http://admin:admin@localhost:3000/api/alertmanager/{{alertManagerDatasourceUID}}/api/v2/alerts ### # get status -GET http://admin:admin@localhost:3000/api/alertmanager/{{alertManagerDatasourceID}}/api/v2/status +GET http://admin:admin@localhost:3000/api/alertmanager/{{alertManagerDatasourceUID}}/api/v2/status ### # get AM alert groups -GET http://admin:admin@localhost:3000/alertmanager/{{alertManagerDatasourceID}}/api/v2/alerts/groups +GET http://admin:admin@localhost:3000/alertmanager/{{alertManagerDatasourceUID}}/api/v2/alerts/groups ### # get silences - no silences -GET http://admin:admin@localhost:3000/api/alertmanager/{{alertManagerDatasourceID}}/api/v2/silences?Filter=foo="bar"&Filter=bar="foo" +GET http://admin:admin@localhost:3000/api/alertmanager/{{alertManagerDatasourceUID}}/api/v2/silences?Filter=foo="bar"&Filter=bar="foo" ### # create silence -POST http://admin:admin@localhost:3000/api/alertmanager/{{alertManagerDatasourceID}}/api/v2/silences +POST http://admin:admin@localhost:3000/api/alertmanager/{{alertManagerDatasourceUID}}/api/v2/silences content-type: application/json { @@ -123,13 +123,13 @@ content-type: application/json ], "createdBy": "spapagian", "comment": "a comment", - "startsAt": "2021-04-05T14:45:09.885Z", - "endsAt": "2021-04-09T16:45:09.885Z" + "startsAt": "2023-04-05T14:45:09.885Z", + "endsAt": "2023-04-09T16:45:09.885Z" } ### # update silence - does not exist -POST http://admin:admin@localhost:3000/api/alertmanager/{{alertManagerDatasourceID}}/api/v2/silences +POST http://admin:admin@localhost:3000/api/alertmanager/{{alertManagerDatasourceUID}}/api/v2/silences content-type: application/json { @@ -150,7 +150,7 @@ content-type: application/json ### # get silences # @name getSilences -GET http://admin:admin@localhost:3000/api/alertmanager/{{alertManagerDatasourceID}}/api/v2/silences +GET http://admin:admin@localhost:3000/api/alertmanager/{{alertManagerDatasourceUID}}/api/v2/silences ### @@ -158,17 +158,17 @@ GET http://admin:admin@localhost:3000/api/alertmanager/{{alertManagerDatasourceI ### # get silence -GET http://admin:admin@localhost:3000/api/alertmanager/{{alertManagerDatasourceID}}/api/v2/silence/{{silenceID}} +GET http://admin:admin@localhost:3000/api/alertmanager/{{alertManagerDatasourceUID}}/api/v2/silence/{{silenceID}} ### # get silence - unknown -GET http://admin:admin@localhost:3000/api/alertmanager/{{alertManagerDatasourceID}}/api/v2/silence/unknown +GET http://admin:admin@localhost:3000/api/alertmanager/{{alertManagerDatasourceUID}}/api/v2/silence/unknown ### # delete silence -DELETE http://admin:admin@localhost:3000/api/alertmanager/{{alertManagerDatasourceID}}/api/v2/silence/{{silenceID}} +DELETE http://admin:admin@localhost:3000/api/alertmanager/{{alertManagerDatasourceUID}}/api/v2/silence/{{silenceID}} ### # delete silence - unknown -DELETE http://admin:admin@localhost:3000/api/alertmanager/{{alertManagerDatasourceID}}/api/v2/silence/unknown +DELETE http://admin:admin@localhost:3000/api/alertmanager/{{alertManagerDatasourceUID}}/api/v2/silence/unknown diff --git a/pkg/services/ngalert/api/tooling/definitions/alertmanager.go b/pkg/services/ngalert/api/tooling/definitions/alertmanager.go index 05db12663b5..c7476c5ca79 100644 --- a/pkg/services/ngalert/api/tooling/definitions/alertmanager.go +++ b/pkg/services/ngalert/api/tooling/definitions/alertmanager.go @@ -30,7 +30,7 @@ import ( // 201: Ack // 400: ValidationError -// swagger:route POST /api/alertmanager/{DatasourceID}/config/api/v1/alerts alertmanager RoutePostAlertingConfig +// swagger:route POST /api/alertmanager/{DatasourceUID}/config/api/v1/alerts alertmanager RoutePostAlertingConfig // // sets an Alerting config // @@ -46,7 +46,7 @@ import ( // 200: GettableUserConfig // 400: ValidationError -// swagger:route GET /api/alertmanager/{DatasourceID}/config/api/v1/alerts alertmanager RouteGetAlertingConfig +// swagger:route GET /api/alertmanager/{DatasourceUID}/config/api/v1/alerts alertmanager RouteGetAlertingConfig // // gets an Alerting config // @@ -62,7 +62,7 @@ import ( // 200: Ack // 400: ValidationError -// swagger:route DELETE /api/alertmanager/{DatasourceID}/config/api/v1/alerts alertmanager RouteDeleteAlertingConfig +// swagger:route DELETE /api/alertmanager/{DatasourceUID}/config/api/v1/alerts alertmanager RouteDeleteAlertingConfig // // deletes the Alerting config for a tenant // @@ -78,7 +78,7 @@ import ( // 200: GettableStatus // 400: ValidationError -// swagger:route GET /api/alertmanager/{DatasourceID}/api/v2/status alertmanager RouteGetAMStatus +// swagger:route GET /api/alertmanager/{DatasourceUID}/api/v2/status alertmanager RouteGetAMStatus // // get alertmanager status and configuration // @@ -94,7 +94,7 @@ import ( // 200: gettableAlerts // 400: ValidationError -// swagger:route GET /api/alertmanager/{DatasourceID}/api/v2/alerts alertmanager RouteGetAMAlerts +// swagger:route GET /api/alertmanager/{DatasourceUID}/api/v2/alerts alertmanager RouteGetAMAlerts // // get alertmanager alerts // @@ -110,7 +110,7 @@ import ( // 200: Ack // 400: ValidationError -// swagger:route POST /api/alertmanager/{DatasourceID}/api/v2/alerts alertmanager RoutePostAMAlerts +// swagger:route POST /api/alertmanager/{DatasourceUID}/api/v2/alerts alertmanager RoutePostAMAlerts // // create alertmanager alerts // @@ -126,7 +126,7 @@ import ( // 200: alertGroups // 400: ValidationError -// swagger:route GET /api/alertmanager/{DatasourceID}/api/v2/alerts/groups alertmanager RouteGetAMAlertGroups +// swagger:route GET /api/alertmanager/{DatasourceUID}/api/v2/alerts/groups alertmanager RouteGetAMAlertGroups // // get alertmanager alerts // @@ -148,7 +148,7 @@ import ( // 408: Failure // 409: AlertManagerNotReady -// swagger:route POST /api/alertmanager/{DatasourceID}/config/api/v1/receivers/test alertmanager RoutePostTestReceivers +// swagger:route POST /api/alertmanager/{DatasourceUID}/config/api/v1/receivers/test alertmanager RoutePostTestReceivers // // Test Grafana managed receivers without saving them. // @@ -170,7 +170,7 @@ import ( // 200: gettableSilences // 400: ValidationError -// swagger:route GET /api/alertmanager/{DatasourceID}/api/v2/silences alertmanager RouteGetSilences +// swagger:route GET /api/alertmanager/{DatasourceUID}/api/v2/silences alertmanager RouteGetSilences // // get silences // @@ -186,7 +186,7 @@ import ( // 201: gettableSilence // 400: ValidationError -// swagger:route POST /api/alertmanager/{DatasourceID}/api/v2/silences alertmanager RouteCreateSilence +// swagger:route POST /api/alertmanager/{DatasourceUID}/api/v2/silences alertmanager RouteCreateSilence // // create silence // @@ -202,7 +202,7 @@ import ( // 200: gettableSilence // 400: ValidationError -// swagger:route GET /api/alertmanager/{DatasourceID}/api/v2/silence/{SilenceId} alertmanager RouteGetSilence +// swagger:route GET /api/alertmanager/{DatasourceUID}/api/v2/silence/{SilenceId} alertmanager RouteGetSilence // // get silence // @@ -218,7 +218,7 @@ import ( // 200: Ack // 400: ValidationError -// swagger:route DELETE /api/alertmanager/{DatasourceID}/api/v2/silence/{SilenceId} alertmanager RouteDeleteSilence +// swagger:route DELETE /api/alertmanager/{DatasourceUID}/api/v2/silence/{SilenceId} alertmanager RouteDeleteSilence // // delete silence // @@ -427,31 +427,39 @@ type AlertsParams struct { } // swagger:parameters RoutePostAMAlerts RoutePostGrafanaAMAlerts +// swagger:parameters RoutePostAMAlerts type PostableAlerts struct { // in:body PostableAlerts []amv2.PostableAlert `yaml:"" json:""` } // swagger:parameters RoutePostAlertingConfig RoutePostGrafanaAlertingConfig +// swagger:parameters RoutePostAlertingConfig type BodyAlertingConfig struct { // in:body Body PostableUserConfig } -// alertmanager routes -// swagger:parameters RoutePostAlertingConfig RouteGetAlertingConfig RouteDeleteAlertingConfig RouteGetAMStatus RouteGetAMAlerts RoutePostAMAlerts RouteGetAMAlertGroups RouteGetSilences RouteCreateSilence RouteGetSilence RouteDeleteSilence RoutePostAlertingConfig RoutePostTestReceivers // ruler routes // swagger:parameters RouteGetRulesConfig RoutePostNameRulesConfig RouteGetNamespaceRulesConfig RouteDeleteNamespaceRulesConfig RouteGetRulegGroupConfig RouteDeleteRuleGroupConfig // prom routes // swagger:parameters RouteGetRuleStatuses RouteGetAlertStatuses // testing routes // swagger:parameters RouteTestReceiverConfig RouteTestRuleConfig -type DatasourceReference struct { - // DatasourceID should be the numeric datasource id +type DatasourceIDReference struct { + // DatasourceID should be the numeric datasource identifier // in:path DatasourceID int } +// alertmanager routes +// swagger:parameters RoutePostAlertingConfig RouteGetAlertingConfig RouteDeleteAlertingConfig RouteGetAMStatus RouteGetAMAlerts RoutePostAMAlerts RouteGetAMAlertGroups RouteGetSilences RouteCreateSilence RouteGetSilence RouteDeleteSilence RoutePostAlertingConfig RoutePostTestReceivers +type DatasourceUIDReference struct { + // DatasoureUID should be the datasource UID identifier + // in:path + DatasourceUID string +} + // swagger:model type PostableUserConfig struct { TemplateFiles map[string]string `yaml:"template_files" json:"template_files"` diff --git a/pkg/services/ngalert/api/tooling/post.json b/pkg/services/ngalert/api/tooling/post.json index d2b8209b342..80dc5b9489a 100644 --- a/pkg/services/ngalert/api/tooling/post.json +++ b/pkg/services/ngalert/api/tooling/post.json @@ -596,7 +596,7 @@ "type": "string", "x-go-name": "Name" }, - "provanance": { + "provenance": { "type": "string", "x-go-name": "Provenance" }, @@ -882,6 +882,9 @@ "type": "string", "x-go-name": "Name" }, + "provenance": { + "$ref": "#/definitions/Provenance" + }, "secureFields": { "additionalProperties": { "type": "boolean" @@ -3100,6 +3103,7 @@ "x-go-package": "github.com/prometheus/alertmanager/api/v2/models" }, "alertGroup": { + "description": "AlertGroup alert group", "properties": { "alerts": { "description": "alerts", @@ -3121,17 +3125,14 @@ "labels", "receiver" ], - "type": "object", - "x-go-name": "AlertGroup", - "x-go-package": "github.com/prometheus/alertmanager/api/v2/models" + "type": "object" }, "alertGroups": { + "description": "AlertGroups alert groups", "items": { "$ref": "#/definitions/alertGroup" }, - "type": "array", - "x-go-name": "AlertGroups", - "x-go-package": "github.com/prometheus/alertmanager/api/v2/models" + "type": "array" }, "alertStatus": { "description": "AlertStatus alert status", @@ -3320,6 +3321,7 @@ "type": "array" }, "gettableSilence": { + "description": "GettableSilence gettable silence", "properties": { "comment": { "description": "comment", @@ -3371,17 +3373,14 @@ "status", "updatedAt" ], - "type": "object", - "x-go-name": "GettableSilence", - "x-go-package": "github.com/prometheus/alertmanager/api/v2/models" + "type": "object" }, "gettableSilences": { + "description": "GettableSilences gettable silences", "items": { "$ref": "#/definitions/gettableSilence" }, - "type": "array", - "x-go-name": "GettableSilences", - "x-go-package": "github.com/prometheus/alertmanager/api/v2/models" + "type": "array" }, "labelSet": { "additionalProperties": { @@ -3510,6 +3509,7 @@ "x-go-package": "github.com/prometheus/alertmanager/api/v2/models" }, "postableSilence": { + "description": "PostableSilence postable silence", "properties": { "comment": { "description": "comment", @@ -3549,9 +3549,7 @@ "matchers", "startsAt" ], - "type": "object", - "x-go-name": "PostableSilence", - "x-go-package": "github.com/prometheus/alertmanager/api/v2/models" + "type": "object" }, "receiver": { "properties": { @@ -4128,7 +4126,7 @@ ] } }, - "/api/alertmanager/{DatasourceID}/api/v2/alerts": { + "/api/alertmanager/{DatasourceUID}/api/v2/alerts": { "get": { "description": "get alertmanager alerts", "operationId": "RouteGetAMAlerts", @@ -4175,12 +4173,11 @@ "x-go-name": "Receivers" }, { - "description": "DatasourceID should be the numeric datasource id", - "format": "int64", + "description": "DatasoureUID should be the datasource UID identifier", "in": "path", - "name": "DatasourceID", + "name": "DatasourceUID", "required": true, - "type": "integer" + "type": "string" } ], "responses": { @@ -4216,12 +4213,11 @@ } }, { - "description": "DatasourceID should be the numeric datasource id", - "format": "int64", + "description": "DatasoureUID should be the datasource UID identifier", "in": "path", - "name": "DatasourceID", + "name": "DatasourceUID", "required": true, - "type": "integer" + "type": "string" } ], "responses": { @@ -4243,7 +4239,7 @@ ] } }, - "/api/alertmanager/{DatasourceID}/api/v2/alerts/groups": { + "/api/alertmanager/{DatasourceUID}/api/v2/alerts/groups": { "get": { "description": "get alertmanager alerts", "operationId": "RouteGetAMAlertGroups", @@ -4290,12 +4286,11 @@ "x-go-name": "Receivers" }, { - "description": "DatasourceID should be the numeric datasource id", - "format": "int64", + "description": "DatasoureUID should be the datasource UID identifier", "in": "path", - "name": "DatasourceID", + "name": "DatasourceUID", "required": true, - "type": "integer" + "type": "string" } ], "responses": { @@ -4317,7 +4312,7 @@ ] } }, - "/api/alertmanager/{DatasourceID}/api/v2/silence/{SilenceId}": { + "/api/alertmanager/{DatasourceUID}/api/v2/silence/{SilenceId}": { "delete": { "description": "delete silence", "operationId": "RouteDeleteSilence", @@ -4329,12 +4324,11 @@ "type": "string" }, { - "description": "DatasourceID should be the numeric datasource id", - "format": "int64", + "description": "DatasoureUID should be the datasource UID identifier", "in": "path", - "name": "DatasourceID", + "name": "DatasourceUID", "required": true, - "type": "integer" + "type": "string" } ], "responses": { @@ -4366,12 +4360,11 @@ "type": "string" }, { - "description": "DatasourceID should be the numeric datasource id", - "format": "int64", + "description": "DatasoureUID should be the datasource UID identifier", "in": "path", - "name": "DatasourceID", + "name": "DatasourceUID", "required": true, - "type": "integer" + "type": "string" } ], "responses": { @@ -4393,7 +4386,7 @@ ] } }, - "/api/alertmanager/{DatasourceID}/api/v2/silences": { + "/api/alertmanager/{DatasourceUID}/api/v2/silences": { "get": { "description": "get silences", "operationId": "RouteGetSilences", @@ -4408,12 +4401,11 @@ "x-go-name": "Filter" }, { - "description": "DatasourceID should be the numeric datasource id", - "format": "int64", + "description": "DatasoureUID should be the datasource UID identifier", "in": "path", - "name": "DatasourceID", + "name": "DatasourceUID", "required": true, - "type": "integer" + "type": "string" } ], "responses": { @@ -4446,12 +4438,11 @@ } }, { - "description": "DatasourceID should be the numeric datasource id", - "format": "int64", + "description": "DatasoureUID should be the datasource UID identifier", "in": "path", - "name": "DatasourceID", + "name": "DatasourceUID", "required": true, - "type": "integer" + "type": "string" } ], "responses": { @@ -4473,18 +4464,17 @@ ] } }, - "/api/alertmanager/{DatasourceID}/api/v2/status": { + "/api/alertmanager/{DatasourceUID}/api/v2/status": { "get": { "description": "get alertmanager status and configuration", "operationId": "RouteGetAMStatus", "parameters": [ { - "description": "DatasourceID should be the numeric datasource id", - "format": "int64", + "description": "DatasoureUID should be the datasource UID identifier", "in": "path", - "name": "DatasourceID", + "name": "DatasourceUID", "required": true, - "type": "integer" + "type": "string" } ], "responses": { @@ -4506,18 +4496,17 @@ ] } }, - "/api/alertmanager/{DatasourceID}/config/api/v1/alerts": { + "/api/alertmanager/{DatasourceUID}/config/api/v1/alerts": { "delete": { "description": "deletes the Alerting config for a tenant", "operationId": "RouteDeleteAlertingConfig", "parameters": [ { - "description": "DatasourceID should be the numeric datasource id", - "format": "int64", + "description": "DatasoureUID should be the datasource UID identifier", "in": "path", - "name": "DatasourceID", + "name": "DatasourceUID", "required": true, - "type": "integer" + "type": "string" } ], "responses": { @@ -4543,12 +4532,11 @@ "operationId": "RouteGetAlertingConfig", "parameters": [ { - "description": "DatasourceID should be the numeric datasource id", - "format": "int64", + "description": "DatasoureUID should be the datasource UID identifier", "in": "path", - "name": "DatasourceID", + "name": "DatasourceUID", "required": true, - "type": "integer" + "type": "string" } ], "responses": { @@ -4581,12 +4569,11 @@ } }, { - "description": "DatasourceID should be the numeric datasource id", - "format": "int64", + "description": "DatasoureUID should be the datasource UID identifier", "in": "path", - "name": "DatasourceID", + "name": "DatasourceUID", "required": true, - "type": "integer" + "type": "string" } ], "responses": { @@ -4608,7 +4595,7 @@ ] } }, - "/api/alertmanager/{DatasourceID}/config/api/v1/receivers/test": { + "/api/alertmanager/{DatasourceUID}/config/api/v1/receivers/test": { "post": { "operationId": "RoutePostTestReceivers", "parameters": [ @@ -4620,12 +4607,11 @@ } }, { - "description": "DatasourceID should be the numeric datasource id", - "format": "int64", + "description": "DatasoureUID should be the datasource UID identifier", "in": "path", - "name": "DatasourceID", + "name": "DatasourceUID", "required": true, - "type": "integer" + "type": "string" } ], "responses": { @@ -4751,7 +4737,7 @@ "operationId": "RouteGetAlertStatuses", "parameters": [ { - "description": "DatasourceID should be the numeric datasource id", + "description": "DatasourceID should be the numeric datasource identifier", "format": "int64", "in": "path", "name": "DatasourceID", @@ -4778,7 +4764,7 @@ "operationId": "RouteGetRuleStatuses", "parameters": [ { - "description": "DatasourceID should be the numeric datasource id", + "description": "DatasourceID should be the numeric datasource identifier", "format": "int64", "in": "path", "name": "DatasourceID", @@ -5182,7 +5168,7 @@ "operationId": "RouteGetRulesConfig", "parameters": [ { - "description": "DatasourceID should be the numeric datasource id", + "description": "DatasourceID should be the numeric datasource identifier", "format": "int64", "in": "path", "name": "DatasourceID", @@ -5223,7 +5209,7 @@ "operationId": "RouteDeleteNamespaceRulesConfig", "parameters": [ { - "description": "DatasourceID should be the numeric datasource id", + "description": "DatasourceID should be the numeric datasource identifier", "format": "int64", "in": "path", "name": "DatasourceID", @@ -5254,7 +5240,7 @@ "operationId": "RouteGetNamespaceRulesConfig", "parameters": [ { - "description": "DatasourceID should be the numeric datasource id", + "description": "DatasourceID should be the numeric datasource identifier", "format": "int64", "in": "path", "name": "DatasourceID", @@ -5292,7 +5278,7 @@ "operationId": "RoutePostNameRulesConfig", "parameters": [ { - "description": "DatasourceID should be the numeric datasource id", + "description": "DatasourceID should be the numeric datasource identifier", "format": "int64", "in": "path", "name": "DatasourceID", @@ -5332,7 +5318,7 @@ "operationId": "RouteDeleteRuleGroupConfig", "parameters": [ { - "description": "DatasourceID should be the numeric datasource id", + "description": "DatasourceID should be the numeric datasource identifier", "format": "int64", "in": "path", "name": "DatasourceID", @@ -5369,7 +5355,7 @@ "operationId": "RouteGetRulegGroupConfig", "parameters": [ { - "description": "DatasourceID should be the numeric datasource id", + "description": "DatasourceID should be the numeric datasource identifier", "format": "int64", "in": "path", "name": "DatasourceID", @@ -5587,7 +5573,7 @@ "operationId": "RouteTestRuleConfig", "parameters": [ { - "description": "DatasourceID should be the numeric datasource id", + "description": "DatasourceID should be the numeric datasource identifier", "format": "int64", "in": "path", "name": "DatasourceID", diff --git a/pkg/services/ngalert/api/tooling/spec.json b/pkg/services/ngalert/api/tooling/spec.json index bc1074572c3..138349e2462 100644 --- a/pkg/services/ngalert/api/tooling/spec.json +++ b/pkg/services/ngalert/api/tooling/spec.json @@ -465,7 +465,7 @@ } } }, - "/api/alertmanager/{DatasourceID}/api/v2/alerts": { + "/api/alertmanager/{DatasourceUID}/api/v2/alerts": { "get": { "description": "get alertmanager alerts", "tags": [ @@ -515,10 +515,9 @@ "in": "query" }, { - "type": "integer", - "format": "int64", - "description": "DatasourceID should be the numeric datasource id", - "name": "DatasourceID", + "type": "string", + "description": "DatasoureUID should be the datasource UID identifier", + "name": "DatasourceUID", "in": "path", "required": true } @@ -556,10 +555,9 @@ } }, { - "type": "integer", - "format": "int64", - "description": "DatasourceID should be the numeric datasource id", - "name": "DatasourceID", + "type": "string", + "description": "DatasoureUID should be the datasource UID identifier", + "name": "DatasourceUID", "in": "path", "required": true } @@ -580,7 +578,7 @@ } } }, - "/api/alertmanager/{DatasourceID}/api/v2/alerts/groups": { + "/api/alertmanager/{DatasourceUID}/api/v2/alerts/groups": { "get": { "description": "get alertmanager alerts", "tags": [ @@ -630,10 +628,9 @@ "in": "query" }, { - "type": "integer", - "format": "int64", - "description": "DatasourceID should be the numeric datasource id", - "name": "DatasourceID", + "type": "string", + "description": "DatasoureUID should be the datasource UID identifier", + "name": "DatasourceUID", "in": "path", "required": true } @@ -654,7 +651,7 @@ } } }, - "/api/alertmanager/{DatasourceID}/api/v2/silence/{SilenceId}": { + "/api/alertmanager/{DatasourceUID}/api/v2/silence/{SilenceId}": { "get": { "description": "get silence", "tags": [ @@ -669,10 +666,9 @@ "required": true }, { - "type": "integer", - "format": "int64", - "description": "DatasourceID should be the numeric datasource id", - "name": "DatasourceID", + "type": "string", + "description": "DatasoureUID should be the datasource UID identifier", + "name": "DatasourceUID", "in": "path", "required": true } @@ -706,10 +702,9 @@ "required": true }, { - "type": "integer", - "format": "int64", - "description": "DatasourceID should be the numeric datasource id", - "name": "DatasourceID", + "type": "string", + "description": "DatasoureUID should be the datasource UID identifier", + "name": "DatasourceUID", "in": "path", "required": true } @@ -730,7 +725,7 @@ } } }, - "/api/alertmanager/{DatasourceID}/api/v2/silences": { + "/api/alertmanager/{DatasourceUID}/api/v2/silences": { "get": { "description": "get silences", "tags": [ @@ -748,10 +743,9 @@ "in": "query" }, { - "type": "integer", - "format": "int64", - "description": "DatasourceID should be the numeric datasource id", - "name": "DatasourceID", + "type": "string", + "description": "DatasoureUID should be the datasource UID identifier", + "name": "DatasourceUID", "in": "path", "required": true } @@ -786,10 +780,9 @@ } }, { - "type": "integer", - "format": "int64", - "description": "DatasourceID should be the numeric datasource id", - "name": "DatasourceID", + "type": "string", + "description": "DatasoureUID should be the datasource UID identifier", + "name": "DatasourceUID", "in": "path", "required": true } @@ -810,7 +803,7 @@ } } }, - "/api/alertmanager/{DatasourceID}/api/v2/status": { + "/api/alertmanager/{DatasourceUID}/api/v2/status": { "get": { "description": "get alertmanager status and configuration", "tags": [ @@ -819,10 +812,9 @@ "operationId": "RouteGetAMStatus", "parameters": [ { - "type": "integer", - "format": "int64", - "description": "DatasourceID should be the numeric datasource id", - "name": "DatasourceID", + "type": "string", + "description": "DatasoureUID should be the datasource UID identifier", + "name": "DatasourceUID", "in": "path", "required": true } @@ -843,7 +835,7 @@ } } }, - "/api/alertmanager/{DatasourceID}/config/api/v1/alerts": { + "/api/alertmanager/{DatasourceUID}/config/api/v1/alerts": { "get": { "description": "gets an Alerting config", "tags": [ @@ -852,10 +844,9 @@ "operationId": "RouteGetAlertingConfig", "parameters": [ { - "type": "integer", - "format": "int64", - "description": "DatasourceID should be the numeric datasource id", - "name": "DatasourceID", + "type": "string", + "description": "DatasoureUID should be the datasource UID identifier", + "name": "DatasourceUID", "in": "path", "required": true } @@ -890,10 +881,9 @@ } }, { - "type": "integer", - "format": "int64", - "description": "DatasourceID should be the numeric datasource id", - "name": "DatasourceID", + "type": "string", + "description": "DatasoureUID should be the datasource UID identifier", + "name": "DatasourceUID", "in": "path", "required": true } @@ -921,10 +911,9 @@ "operationId": "RouteDeleteAlertingConfig", "parameters": [ { - "type": "integer", - "format": "int64", - "description": "DatasourceID should be the numeric datasource id", - "name": "DatasourceID", + "type": "string", + "description": "DatasoureUID should be the datasource UID identifier", + "name": "DatasourceUID", "in": "path", "required": true } @@ -945,7 +934,7 @@ } } }, - "/api/alertmanager/{DatasourceID}/config/api/v1/receivers/test": { + "/api/alertmanager/{DatasourceUID}/config/api/v1/receivers/test": { "post": { "tags": [ "alertmanager" @@ -961,10 +950,9 @@ } }, { - "type": "integer", - "format": "int64", - "description": "DatasourceID should be the numeric datasource id", - "name": "DatasourceID", + "type": "string", + "description": "DatasoureUID should be the datasource UID identifier", + "name": "DatasourceUID", "in": "path", "required": true } @@ -1093,7 +1081,7 @@ { "type": "integer", "format": "int64", - "description": "DatasourceID should be the numeric datasource id", + "description": "DatasourceID should be the numeric datasource identifier", "name": "DatasourceID", "in": "path", "required": true @@ -1120,7 +1108,7 @@ { "type": "integer", "format": "int64", - "description": "DatasourceID should be the numeric datasource id", + "description": "DatasourceID should be the numeric datasource identifier", "name": "DatasourceID", "in": "path", "required": true @@ -1527,7 +1515,7 @@ { "type": "integer", "format": "int64", - "description": "DatasourceID should be the numeric datasource id", + "description": "DatasourceID should be the numeric datasource identifier", "name": "DatasourceID", "in": "path", "required": true @@ -1568,7 +1556,7 @@ { "type": "integer", "format": "int64", - "description": "DatasourceID should be the numeric datasource id", + "description": "DatasourceID should be the numeric datasource identifier", "name": "DatasourceID", "in": "path", "required": true @@ -1603,7 +1591,7 @@ { "type": "integer", "format": "int64", - "description": "DatasourceID should be the numeric datasource id", + "description": "DatasourceID should be the numeric datasource identifier", "name": "DatasourceID", "in": "path", "required": true @@ -1641,7 +1629,7 @@ { "type": "integer", "format": "int64", - "description": "DatasourceID should be the numeric datasource id", + "description": "DatasourceID should be the numeric datasource identifier", "name": "DatasourceID", "in": "path", "required": true @@ -1677,7 +1665,7 @@ { "type": "integer", "format": "int64", - "description": "DatasourceID should be the numeric datasource id", + "description": "DatasourceID should be the numeric datasource identifier", "name": "DatasourceID", "in": "path", "required": true @@ -1714,7 +1702,7 @@ { "type": "integer", "format": "int64", - "description": "DatasourceID should be the numeric datasource id", + "description": "DatasourceID should be the numeric datasource identifier", "name": "DatasourceID", "in": "path", "required": true @@ -1932,7 +1920,7 @@ { "type": "integer", "format": "int64", - "description": "DatasourceID should be the numeric datasource id", + "description": "DatasourceID should be the numeric datasource identifier", "name": "DatasourceID", "in": "path", "required": true @@ -2551,7 +2539,7 @@ "type": "string", "x-go-name": "Name" }, - "provanance": { + "provenance": { "type": "string", "x-go-name": "Provenance" }, @@ -2839,6 +2827,9 @@ "type": "string", "x-go-name": "Name" }, + "provenance": { + "$ref": "#/definitions/Provenance" + }, "secureFields": { "type": "object", "additionalProperties": { @@ -5057,6 +5048,7 @@ "x-go-package": "github.com/prometheus/alertmanager/api/v2/models" }, "alertGroup": { + "description": "AlertGroup alert group", "type": "object", "required": [ "alerts", @@ -5079,17 +5071,14 @@ "$ref": "#/definitions/receiver" } }, - "x-go-name": "AlertGroup", - "x-go-package": "github.com/prometheus/alertmanager/api/v2/models", "$ref": "#/definitions/alertGroup" }, "alertGroups": { + "description": "AlertGroups alert groups", "type": "array", "items": { "$ref": "#/definitions/alertGroup" }, - "x-go-name": "AlertGroups", - "x-go-package": "github.com/prometheus/alertmanager/api/v2/models", "$ref": "#/definitions/alertGroups" }, "alertStatus": { @@ -5281,6 +5270,7 @@ "$ref": "#/definitions/gettableAlerts" }, "gettableSilence": { + "description": "GettableSilence gettable silence", "type": "object", "required": [ "comment", @@ -5333,17 +5323,14 @@ "x-go-name": "UpdatedAt" } }, - "x-go-name": "GettableSilence", - "x-go-package": "github.com/prometheus/alertmanager/api/v2/models", "$ref": "#/definitions/gettableSilence" }, "gettableSilences": { + "description": "GettableSilences gettable silences", "type": "array", "items": { "$ref": "#/definitions/gettableSilence" }, - "x-go-name": "GettableSilences", - "x-go-package": "github.com/prometheus/alertmanager/api/v2/models", "$ref": "#/definitions/gettableSilences" }, "labelSet": { @@ -5473,6 +5460,7 @@ "x-go-package": "github.com/prometheus/alertmanager/api/v2/models" }, "postableSilence": { + "description": "PostableSilence postable silence", "type": "object", "required": [ "comment", @@ -5513,8 +5501,6 @@ "x-go-name": "StartsAt" } }, - "x-go-name": "PostableSilence", - "x-go-package": "github.com/prometheus/alertmanager/api/v2/models", "$ref": "#/definitions/postableSilence" }, "receiver": { diff --git a/pkg/services/ngalert/api/util.go b/pkg/services/ngalert/api/util.go index ce5e8c1ef24..ed079702b2f 100644 --- a/pkg/services/ngalert/api/util.go +++ b/pkg/services/ngalert/api/util.go @@ -52,6 +52,21 @@ func backendType(ctx *models.ReqContext, cache datasources.CacheService) (apimod return 0, fmt.Errorf("unexpected backend type (%v)", datasourceID) } +func backendTypeByUID(ctx *models.ReqContext, cache datasources.CacheService) (apimodels.Backend, error) { + datasourceUID := web.Params(ctx.Req)[":DatasourceUID"] + if ds, err := cache.GetDatasourceByUID(ctx.Req.Context(), datasourceUID, ctx.SignedInUser, ctx.SkipCache); err == nil { + switch ds.Type { + case "loki", "prometheus": + return apimodels.LoTexRulerBackend, nil + case "alertmanager": + return apimodels.AlertmanagerBackend, nil + default: + return 0, fmt.Errorf("unexpected backend type (%v)", ds.Type) + } + } + return 0, fmt.Errorf("unexpected backend type (%v)", datasourceUID) +} + // macaron unsafely asserts the http.ResponseWriter is an http.CloseNotifier, which will panic. // Here we impl it, which will ensure this no longer happens, but neither will we take // advantage cancelling upstream requests when the downstream has closed. @@ -98,12 +113,21 @@ func (p *AlertingProxy) withReq( newCtx, resp := replacedResponseWriter(ctx) newCtx.Req = req - datasourceID, err := strconv.ParseInt(web.Params(ctx.Req)[":DatasourceID"], 10, 64) - if err != nil { - return ErrResp(http.StatusBadRequest, err, "DatasourceID is invalid") - } + datasourceID := web.Params(ctx.Req)[":DatasourceID"] + if datasourceID != "" { + recipient, err := strconv.ParseInt(web.Params(ctx.Req)[":DatasourceID"], 10, 64) + if err != nil { + return ErrResp(http.StatusBadRequest, err, "DatasourceID is invalid") + } - p.DataProxy.ProxyDatasourceRequestWithID(newCtx, datasourceID) + p.DataProxy.ProxyDatasourceRequestWithID(newCtx, recipient) + } else { + datasourceUID := web.Params(ctx.Req)[":DatasourceUID"] + if datasourceUID == "" { + return ErrResp(http.StatusBadRequest, err, "DatasourceUID is empty") + } + p.DataProxy.ProxyDatasourceRequestWithUID(newCtx, datasourceUID) + } status := resp.Status() if status >= 400 { diff --git a/public/api-merged.json b/public/api-merged.json index 51601635d42..63ebf3f33ac 100644 --- a/public/api-merged.json +++ b/public/api-merged.json @@ -2217,7 +2217,7 @@ } } }, - "/alertmanager/{DatasourceID}/api/v2/alerts": { + "/alertmanager/{DatasourceUID}/api/v2/alerts": { "get": { "description": "get alertmanager alerts", "tags": ["alertmanager"], @@ -2265,10 +2265,9 @@ "in": "query" }, { - "type": "integer", - "format": "int64", - "description": "DatasourceID should be the numeric datasource id", - "name": "DatasourceID", + "type": "string", + "description": "DatasoureUID should be the datasource UID identifier", + "name": "DatasourceUID", "in": "path", "required": true } @@ -2304,10 +2303,9 @@ } }, { - "type": "integer", - "format": "int64", - "description": "DatasourceID should be the numeric datasource id", - "name": "DatasourceID", + "type": "string", + "description": "DatasoureUID should be the datasource UID identifier", + "name": "DatasourceUID", "in": "path", "required": true } @@ -2328,7 +2326,7 @@ } } }, - "/alertmanager/{DatasourceID}/api/v2/alerts/groups": { + "/alertmanager/{DatasourceUID}/api/v2/alerts/groups": { "get": { "description": "get alertmanager alerts", "tags": ["alertmanager"], @@ -2376,10 +2374,9 @@ "in": "query" }, { - "type": "integer", - "format": "int64", - "description": "DatasourceID should be the numeric datasource id", - "name": "DatasourceID", + "type": "string", + "description": "DatasoureUID should be the datasource UID identifier", + "name": "DatasourceUID", "in": "path", "required": true } @@ -2400,7 +2397,7 @@ } } }, - "/alertmanager/{DatasourceID}/api/v2/silence/{SilenceId}": { + "/alertmanager/{DatasourceUID}/api/v2/silence/{SilenceId}": { "get": { "description": "get silence", "tags": ["alertmanager"], @@ -2413,10 +2410,9 @@ "required": true }, { - "type": "integer", - "format": "int64", - "description": "DatasourceID should be the numeric datasource id", - "name": "DatasourceID", + "type": "string", + "description": "DatasoureUID should be the datasource UID identifier", + "name": "DatasourceUID", "in": "path", "required": true } @@ -2448,10 +2444,9 @@ "required": true }, { - "type": "integer", - "format": "int64", - "description": "DatasourceID should be the numeric datasource id", - "name": "DatasourceID", + "type": "string", + "description": "DatasoureUID should be the datasource UID identifier", + "name": "DatasourceUID", "in": "path", "required": true } @@ -2472,7 +2467,7 @@ } } }, - "/alertmanager/{DatasourceID}/api/v2/silences": { + "/alertmanager/{DatasourceUID}/api/v2/silences": { "get": { "description": "get silences", "tags": ["alertmanager"], @@ -2488,10 +2483,9 @@ "in": "query" }, { - "type": "integer", - "format": "int64", - "description": "DatasourceID should be the numeric datasource id", - "name": "DatasourceID", + "type": "string", + "description": "DatasoureUID should be the datasource UID identifier", + "name": "DatasourceUID", "in": "path", "required": true } @@ -2524,10 +2518,9 @@ } }, { - "type": "integer", - "format": "int64", - "description": "DatasourceID should be the numeric datasource id", - "name": "DatasourceID", + "type": "string", + "description": "DatasoureUID should be the datasource UID identifier", + "name": "DatasourceUID", "in": "path", "required": true } @@ -2548,17 +2541,16 @@ } } }, - "/alertmanager/{DatasourceID}/api/v2/status": { + "/alertmanager/{DatasourceUID}/api/v2/status": { "get": { "description": "get alertmanager status and configuration", "tags": ["alertmanager"], "operationId": "RouteGetAMStatus", "parameters": [ { - "type": "integer", - "format": "int64", - "description": "DatasourceID should be the numeric datasource id", - "name": "DatasourceID", + "type": "string", + "description": "DatasoureUID should be the datasource UID identifier", + "name": "DatasourceUID", "in": "path", "required": true } @@ -2579,17 +2571,16 @@ } } }, - "/alertmanager/{DatasourceID}/config/api/v1/alerts": { + "/alertmanager/{DatasourceUID}/config/api/v1/alerts": { "get": { "description": "gets an Alerting config", "tags": ["alertmanager"], "operationId": "RouteGetAlertingConfig", "parameters": [ { - "type": "integer", - "format": "int64", - "description": "DatasourceID should be the numeric datasource id", - "name": "DatasourceID", + "type": "string", + "description": "DatasoureUID should be the datasource UID identifier", + "name": "DatasourceUID", "in": "path", "required": true } @@ -2622,10 +2613,9 @@ } }, { - "type": "integer", - "format": "int64", - "description": "DatasourceID should be the numeric datasource id", - "name": "DatasourceID", + "type": "string", + "description": "DatasoureUID should be the datasource UID identifier", + "name": "DatasourceUID", "in": "path", "required": true } @@ -2651,10 +2641,9 @@ "operationId": "RouteDeleteAlertingConfig", "parameters": [ { - "type": "integer", - "format": "int64", - "description": "DatasourceID should be the numeric datasource id", - "name": "DatasourceID", + "type": "string", + "description": "DatasoureUID should be the datasource UID identifier", + "name": "DatasourceUID", "in": "path", "required": true } @@ -2675,7 +2664,7 @@ } } }, - "/alertmanager/{DatasourceID}/config/api/v1/receivers/test": { + "/alertmanager/{DatasourceUID}/config/api/v1/receivers/test": { "post": { "tags": ["alertmanager"], "summary": "Test Grafana managed receivers without saving them.", @@ -2689,10 +2678,9 @@ } }, { - "type": "integer", - "format": "int64", - "description": "DatasourceID should be the numeric datasource id", - "name": "DatasourceID", + "type": "string", + "description": "DatasoureUID should be the datasource UID identifier", + "name": "DatasourceUID", "in": "path", "required": true } @@ -6638,7 +6626,7 @@ { "type": "integer", "format": "int64", - "description": "DatasourceID should be the numeric datasource id", + "description": "DatasourceID should be the numeric datasource identifier", "name": "DatasourceID", "in": "path", "required": true @@ -6663,7 +6651,7 @@ { "type": "integer", "format": "int64", - "description": "DatasourceID should be the numeric datasource id", + "description": "DatasourceID should be the numeric datasource identifier", "name": "DatasourceID", "in": "path", "required": true @@ -7576,7 +7564,7 @@ { "type": "integer", "format": "int64", - "description": "DatasourceID should be the numeric datasource id", + "description": "DatasourceID should be the numeric datasource identifier", "name": "DatasourceID", "in": "path", "required": true @@ -7613,7 +7601,7 @@ { "type": "integer", "format": "int64", - "description": "DatasourceID should be the numeric datasource id", + "description": "DatasourceID should be the numeric datasource identifier", "name": "DatasourceID", "in": "path", "required": true @@ -7643,7 +7631,7 @@ { "type": "integer", "format": "int64", - "description": "DatasourceID should be the numeric datasource id", + "description": "DatasourceID should be the numeric datasource identifier", "name": "DatasourceID", "in": "path", "required": true @@ -7679,7 +7667,7 @@ { "type": "integer", "format": "int64", - "description": "DatasourceID should be the numeric datasource id", + "description": "DatasourceID should be the numeric datasource identifier", "name": "DatasourceID", "in": "path", "required": true @@ -7711,7 +7699,7 @@ { "type": "integer", "format": "int64", - "description": "DatasourceID should be the numeric datasource id", + "description": "DatasourceID should be the numeric datasource identifier", "name": "DatasourceID", "in": "path", "required": true @@ -7746,7 +7734,7 @@ { "type": "integer", "format": "int64", - "description": "DatasourceID should be the numeric datasource id", + "description": "DatasourceID should be the numeric datasource identifier", "name": "DatasourceID", "in": "path", "required": true @@ -9547,7 +9535,7 @@ { "type": "integer", "format": "int64", - "description": "DatasourceID should be the numeric datasource id", + "description": "DatasourceID should be the numeric datasource identifier", "name": "DatasourceID", "in": "path", "required": true @@ -12018,7 +12006,7 @@ "type": "string", "x-go-name": "Name" }, - "provanance": { + "provenance": { "type": "string", "x-go-name": "Provenance" }, @@ -12510,6 +12498,9 @@ "type": "string", "x-go-name": "Name" }, + "provenance": { + "$ref": "#/definitions/Provenance" + }, "secureFields": { "type": "object", "additionalProperties": { @@ -16314,8 +16305,9 @@ "x-go-package": "github.com/grafana/grafana/pkg/api/dtos" }, "URL": { + "description": "The general form represented is:\n\n[scheme:][//[userinfo@]host][/]path[?query][#fragment]\n\nURLs that do not start with a slash after the scheme are interpreted as:\n\nscheme:opaque[?query][#fragment]\n\nNote that the Path field is stored in decoded form: /%47%6f%2f becomes /Go/.\nA consequence is that it is impossible to tell which slashes in the Path were\nslashes in the raw URL and which were %2f. This distinction is rarely important,\nbut when it is, the code should use RawPath, an optional field which only gets\nset if the default encoding is different from Path.\n\nURL's String method uses the EscapedPath method to obtain the path. See the\nEscapedPath method for more details.", "type": "object", - "title": "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" @@ -16348,7 +16340,7 @@ "$ref": "#/definitions/Userinfo" } }, - "x-go-package": "github.com/prometheus/common/config" + "x-go-package": "net/url" }, "UpdateAlertNotificationCommand": { "type": "object", @@ -17237,6 +17229,7 @@ "x-go-package": "github.com/prometheus/alertmanager/api/v2/models" }, "alertGroup": { + "description": "AlertGroup alert group", "type": "object", "required": ["alerts", "labels", "receiver"], "properties": { @@ -17254,17 +17247,14 @@ "receiver": { "$ref": "#/definitions/receiver" } - }, - "x-go-name": "AlertGroup", - "x-go-package": "github.com/prometheus/alertmanager/api/v2/models" + } }, "alertGroups": { + "description": "AlertGroups alert groups", "type": "array", "items": { "$ref": "#/definitions/alertGroup" - }, - "x-go-name": "AlertGroups", - "x-go-package": "github.com/prometheus/alertmanager/api/v2/models" + } }, "alertStatus": { "description": "AlertStatus alert status", @@ -17427,6 +17417,7 @@ } }, "gettableSilence": { + "description": "GettableSilence gettable silence", "type": "object", "required": ["comment", "createdBy", "endsAt", "matchers", "startsAt", "id", "status", "updatedAt"], "properties": { @@ -17469,17 +17460,14 @@ "format": "date-time", "x-go-name": "UpdatedAt" } - }, - "x-go-name": "GettableSilence", - "x-go-package": "github.com/prometheus/alertmanager/api/v2/models" + } }, "gettableSilences": { + "description": "GettableSilences gettable silences", "type": "array", "items": { "$ref": "#/definitions/gettableSilence" - }, - "x-go-name": "GettableSilences", - "x-go-package": "github.com/prometheus/alertmanager/api/v2/models" + } }, "labelSet": { "description": "LabelSet label set", @@ -17599,6 +17587,7 @@ "x-go-package": "github.com/prometheus/alertmanager/api/v2/models" }, "postableSilence": { + "description": "PostableSilence postable silence", "type": "object", "required": ["comment", "createdBy", "endsAt", "matchers", "startsAt"], "properties": { @@ -17632,9 +17621,7 @@ "format": "date-time", "x-go-name": "StartsAt" } - }, - "x-go-name": "PostableSilence", - "x-go-package": "github.com/prometheus/alertmanager/api/v2/models" + } }, "receiver": { "description": "Receiver receiver", diff --git a/public/app/features/alerting/unified/api/alertmanager.ts b/public/app/features/alerting/unified/api/alertmanager.ts index fe73d3fd655..28649614ab8 100644 --- a/public/app/features/alerting/unified/api/alertmanager.ts +++ b/public/app/features/alerting/unified/api/alertmanager.ts @@ -19,14 +19,14 @@ import { } from 'app/plugins/datasource/alertmanager/types'; import { isFetchError } from '../utils/alertmanager'; -import { getDatasourceAPIId, GRAFANA_RULES_SOURCE_NAME } from '../utils/datasource'; +import { getDatasourceAPIUid, GRAFANA_RULES_SOURCE_NAME } from '../utils/datasource'; // "grafana" for grafana-managed, otherwise a datasource name export async function fetchAlertManagerConfig(alertManagerSourceName: string): Promise { try { const result = await lastValueFrom( getBackendSrv().fetch({ - url: `/api/alertmanager/${getDatasourceAPIId(alertManagerSourceName)}/config/api/v1/alerts`, + url: `/api/alertmanager/${getDatasourceAPIUid(alertManagerSourceName)}/config/api/v1/alerts`, showErrorAlert: false, showSuccessAlert: false, }) @@ -57,7 +57,7 @@ export async function updateAlertManagerConfig( await lastValueFrom( getBackendSrv().fetch({ method: 'POST', - url: `/api/alertmanager/${getDatasourceAPIId(alertManagerSourceName)}/config/api/v1/alerts`, + url: `/api/alertmanager/${getDatasourceAPIUid(alertManagerSourceName)}/config/api/v1/alerts`, data: config, showErrorAlert: false, showSuccessAlert: false, @@ -69,7 +69,7 @@ export async function deleteAlertManagerConfig(alertManagerSourceName: string): await lastValueFrom( getBackendSrv().fetch({ method: 'DELETE', - url: `/api/alertmanager/${getDatasourceAPIId(alertManagerSourceName)}/config/api/v1/alerts`, + url: `/api/alertmanager/${getDatasourceAPIUid(alertManagerSourceName)}/config/api/v1/alerts`, showErrorAlert: false, showSuccessAlert: false, }) @@ -79,7 +79,7 @@ export async function deleteAlertManagerConfig(alertManagerSourceName: string): export async function fetchSilences(alertManagerSourceName: string): Promise { const result = await lastValueFrom( getBackendSrv().fetch({ - url: `/api/alertmanager/${getDatasourceAPIId(alertManagerSourceName)}/api/v2/silences`, + url: `/api/alertmanager/${getDatasourceAPIUid(alertManagerSourceName)}/api/v2/silences`, showErrorAlert: false, showSuccessAlert: false, }) @@ -94,7 +94,7 @@ export async function createOrUpdateSilence( ): Promise { const result = await lastValueFrom( getBackendSrv().fetch({ - url: `/api/alertmanager/${getDatasourceAPIId(alertmanagerSourceName)}/api/v2/silences`, + url: `/api/alertmanager/${getDatasourceAPIUid(alertmanagerSourceName)}/api/v2/silences`, data: payload, showErrorAlert: false, showSuccessAlert: false, @@ -106,7 +106,7 @@ export async function createOrUpdateSilence( export async function expireSilence(alertmanagerSourceName: string, silenceID: string): Promise { await getBackendSrv().delete( - `/api/alertmanager/${getDatasourceAPIId(alertmanagerSourceName)}/api/v2/silence/${encodeURIComponent(silenceID)}` + `/api/alertmanager/${getDatasourceAPIUid(alertmanagerSourceName)}/api/v2/silence/${encodeURIComponent(silenceID)}` ); } @@ -131,7 +131,7 @@ export async function fetchAlerts( const result = await lastValueFrom( getBackendSrv().fetch({ url: - `/api/alertmanager/${getDatasourceAPIId(alertmanagerSourceName)}/api/v2/alerts` + + `/api/alertmanager/${getDatasourceAPIUid(alertmanagerSourceName)}/api/v2/alerts` + (filters ? '?' + filters : ''), showErrorAlert: false, showSuccessAlert: false, @@ -144,7 +144,7 @@ export async function fetchAlerts( export async function fetchAlertGroups(alertmanagerSourceName: string): Promise { const result = await lastValueFrom( getBackendSrv().fetch({ - url: `/api/alertmanager/${getDatasourceAPIId(alertmanagerSourceName)}/api/v2/alerts/groups`, + url: `/api/alertmanager/${getDatasourceAPIUid(alertmanagerSourceName)}/api/v2/alerts/groups`, showErrorAlert: false, showSuccessAlert: false, }) @@ -156,7 +156,7 @@ export async function fetchAlertGroups(alertmanagerSourceName: string): Promise< export async function fetchStatus(alertManagerSourceName: string): Promise { const result = await lastValueFrom( getBackendSrv().fetch({ - url: `/api/alertmanager/${getDatasourceAPIId(alertManagerSourceName)}/api/v2/status`, + url: `/api/alertmanager/${getDatasourceAPIUid(alertManagerSourceName)}/api/v2/status`, showErrorAlert: false, showSuccessAlert: false, }) @@ -179,7 +179,7 @@ export async function testReceivers( getBackendSrv().fetch({ method: 'POST', data, - url: `/api/alertmanager/${getDatasourceAPIId(alertManagerSourceName)}/config/api/v1/receivers/test`, + url: `/api/alertmanager/${getDatasourceAPIUid(alertManagerSourceName)}/config/api/v1/receivers/test`, showErrorAlert: false, showSuccessAlert: false, }) diff --git a/public/app/features/alerting/unified/utils/datasource.ts b/public/app/features/alerting/unified/utils/datasource.ts index 4a17af4c216..b13997c4d78 100644 --- a/public/app/features/alerting/unified/utils/datasource.ts +++ b/public/app/features/alerting/unified/utils/datasource.ts @@ -111,3 +111,14 @@ export function getDatasourceAPIId(dataSourceName: string) { } return String(ds.id); } + +export function getDatasourceAPIUid(dataSourceName: string) { + if (dataSourceName === GRAFANA_RULES_SOURCE_NAME) { + return GRAFANA_RULES_SOURCE_NAME; + } + const ds = getDataSourceByName(dataSourceName); + if (!ds) { + throw new Error(`Datasource "${dataSourceName}" not found`); + } + return ds.uid; +}