diff --git a/docs/sources/http_api/data_source.md b/docs/sources/http_api/data_source.md index 20f5cb0e5e1..c3613ffaa7c 100644 --- a/docs/sources/http_api/data_source.md +++ b/docs/sources/http_api/data_source.md @@ -604,6 +604,162 @@ Content-Type: application/json Proxies all calls to the actual data source. +## Check data source health by id + +> **Warning:** This API is deprecated since Grafana v9.0.0 and will be removed in a future release. Refer to the [new data source health check API](#check-data-source-health). + +`GET /api/datasources/:datasourceId/health` + +Makes a call to the health endpoint of data source identified by the given `dashboardId`. + +### Examples + +**Example Request**: + +```http +GET api/datasources/112/health HTTP/1.1 +Accept: application/json +Content-Type: application/json +Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk +``` + +**Example Response**: + +```http +HTTP/1.1 200 +Content-Type: application/json + +{ + "message": "1. Successfully queried the CloudWatch metrics API.\n2. Successfully queried the CloudWatch logs API.", + "status": "OK" +} +``` + +## Check data source health + +`GET /api/datasources/uid/:uid/health` + +Makes a call to the health endpoint of data source identified by the given `uid`. + +### Examples + +**Example Request**: + +```http +GET api/datasources/uid/P8045C56BDA891CB2/health HTTP/1.1 +Accept: application/json +Content-Type: application/json +Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk +``` + +**Example Response**: + +```http +HTTP/1.1 200 +Content-Type: application/json + +{ + "message": "1. Successfully queried the CloudWatch metrics API.\n2. Successfully queried the CloudWatch logs API.", + "status": "OK" +} +``` + +## Fetch data source resources by id + +> **Warning:** This API is deprecated since Grafana v9.0.0 and will be removed in a future release. Refer to the [new data source resources API](#fetch-data-source-resources). + +`GET /api/datasources/:datasourceId/resources/*` + +Makes a call to the resources endpoint of data source identified by the given `dashboardId`. + +### Examples + +**Example Request**: + +```http +GET api/datasources/112/resources/dimension-keys?region=us-east-2&namespace=AWS%2FEC2&dimensionFilters=%7B%7D&metricName=CPUUtilization HTTP/1.1 +Accept: application/json +Content-Type: application/json +Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk +``` + +**Example Response**: + +```http +HTTP/1.1 200 +Content-Type: application/json + +[ + { + "text": "AutoScalingGroupName", + "value": "AutoScalingGroupName", + "label": "AutoScalingGroupName" + }, + { + "text": "ImageId", + "value": "ImageId", + "label": "ImageId" + }, + { + "text": "InstanceId", + "value": "InstanceId", + "label": "InstanceId" + }, + { + "text": "InstanceType", + "value": "InstanceType", + "label": "InstanceType" + } +] +``` + +## Fetch data source resources + +`GET /api/datasources/uid/:uid/resources/*` + +Makes a call to the resources endpoint of data source identified by the given `uid`. + +### Examples + +**Example Request**: + +```http +GET api/datasources/uid/P8045C56BDA891CB2/resources/dimension-keys?region=us-east-2&namespace=AWS%2FEC2&dimensionFilters=%7B%7D&metricName=CPUUtilization HTTP/1.1 +Accept: application/json +Content-Type: application/json +Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk +``` + +**Example Response**: + +```http +HTTP/1.1 200 +Content-Type: application/json + +[ + { + "text": "AutoScalingGroupName", + "value": "AutoScalingGroupName", + "label": "AutoScalingGroupName" + }, + { + "text": "ImageId", + "value": "ImageId", + "label": "ImageId" + }, + { + "text": "InstanceId", + "value": "InstanceId", + "label": "InstanceId" + }, + { + "text": "InstanceType", + "value": "InstanceType", + "label": "InstanceType" + } +] +``` + ## Query a data source Queries a data source having a backend implementation. diff --git a/pkg/api/api.go b/pkg/api/api.go index 94f3b0b45ce..6ee95a2cd36 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -340,9 +340,15 @@ func (hs *HTTPServer) registerRoutes() { apiRoute.Any("/datasources/proxy/uid/:uid/*", authorize(reqSignedIn, ac.EvalPermission(datasources.ActionQuery)), hs.ProxyDataSourceRequestWithUID) apiRoute.Any("/datasources/proxy/:id", authorize(reqSignedIn, ac.EvalPermission(datasources.ActionQuery)), hs.ProxyDataSourceRequest) apiRoute.Any("/datasources/proxy/uid/:uid", authorize(reqSignedIn, ac.EvalPermission(datasources.ActionQuery)), hs.ProxyDataSourceRequestWithUID) + // Deprecated: use /datasources/uid/:uid/resources API instead. apiRoute.Any("/datasources/:id/resources", authorize(reqSignedIn, ac.EvalPermission(datasources.ActionQuery)), hs.CallDatasourceResource) + apiRoute.Any("/datasources/uid/:uid/resources", authorize(reqSignedIn, ac.EvalPermission(datasources.ActionQuery)), hs.CallDatasourceResourceWithUID) + // Deprecated: use /datasources/uid/:uid/resources/* API instead. apiRoute.Any("/datasources/:id/resources/*", authorize(reqSignedIn, ac.EvalPermission(datasources.ActionQuery)), hs.CallDatasourceResource) + apiRoute.Any("/datasources/uid/:uid/resources/*", authorize(reqSignedIn, ac.EvalPermission(datasources.ActionQuery)), hs.CallDatasourceResourceWithUID) + // Deprecated: use /datasources/uid/:uid/health API instead. apiRoute.Any("/datasources/:id/health", authorize(reqSignedIn, ac.EvalPermission(datasources.ActionQuery)), routing.Wrap(hs.CheckDatasourceHealth)) + apiRoute.Any("/datasources/uid/:uid/health", authorize(reqSignedIn, ac.EvalPermission(datasources.ActionQuery)), routing.Wrap(hs.CheckDatasourceHealthWithUID)) // Folders apiRoute.Group("/folders", func(folderRoute routing.RouteRegister) { diff --git a/pkg/api/datasources.go b/pkg/api/datasources.go index 500d113cc15..44e3da78ac5 100644 --- a/pkg/api/datasources.go +++ b/pkg/api/datasources.go @@ -425,6 +425,33 @@ func (hs *HTTPServer) CallDatasourceResource(c *models.ReqContext) { hs.callPluginResourceWithDataSource(c, plugin.ID, ds) } +// /api/datasources/uid/:uid/resources/* +func (hs *HTTPServer) CallDatasourceResourceWithUID(c *models.ReqContext) { + dsUID := web.Params(c.Req)[":uid"] + if !util.IsValidShortUID(dsUID) { + c.JsonApiErr(http.StatusBadRequest, "UID is invalid", nil) + return + } + + ds, err := hs.DataSourceCache.GetDatasourceByUID(c.Req.Context(), dsUID, c.SignedInUser, c.SkipCache) + if err != nil { + if errors.Is(err, models.ErrDataSourceAccessDenied) { + c.JsonApiErr(http.StatusForbidden, "Access denied to datasource", err) + return + } + c.JsonApiErr(http.StatusInternalServerError, "Unable to load datasource meta data", err) + return + } + + plugin, exists := hs.pluginStore.Plugin(c.Req.Context(), ds.Type) + if !exists { + c.JsonApiErr(http.StatusInternalServerError, "Unable to find datasource plugin", err) + return + } + + hs.callPluginResourceWithDataSource(c, plugin.ID, ds) +} + func (hs *HTTPServer) convertModelToDtos(ctx context.Context, ds *models.DataSource) dtos.DataSource { dto := dtos.DataSource{ Id: ds.Id, @@ -462,6 +489,24 @@ func (hs *HTTPServer) convertModelToDtos(ctx context.Context, ds *models.DataSou return dto } +// CheckDatasourceHealthWithUID sends a health check request to the plugin datasource +// /api/datasource/uid/:uid/health +func (hs *HTTPServer) CheckDatasourceHealthWithUID(c *models.ReqContext) response.Response { + dsUID := web.Params(c.Req)[":uid"] + if !util.IsValidShortUID(dsUID) { + return response.Error(http.StatusBadRequest, "UID is invalid", nil) + } + + ds, err := hs.DataSourceCache.GetDatasourceByUID(c.Req.Context(), dsUID, c.SignedInUser, c.SkipCache) + if err != nil { + if errors.Is(err, models.ErrDataSourceAccessDenied) { + return response.Error(http.StatusForbidden, "Access denied to datasource", err) + } + return response.Error(http.StatusInternalServerError, "Unable to load datasource metadata", err) + } + return hs.checkDatasourceHealth(c, ds) +} + // CheckDatasourceHealth sends a health check request to the plugin datasource // /api/datasource/:id/health func (hs *HTTPServer) CheckDatasourceHealth(c *models.ReqContext) response.Response { @@ -477,10 +522,13 @@ func (hs *HTTPServer) CheckDatasourceHealth(c *models.ReqContext) response.Respo } return response.Error(http.StatusInternalServerError, "Unable to load datasource metadata", err) } + return hs.checkDatasourceHealth(c, ds) +} +func (hs *HTTPServer) checkDatasourceHealth(c *models.ReqContext, ds *models.DataSource) response.Response { plugin, exists := hs.pluginStore.Plugin(c.Req.Context(), ds.Type) if !exists { - return response.Error(http.StatusInternalServerError, "Unable to find datasource plugin", err) + return response.Error(http.StatusInternalServerError, "Unable to find datasource plugin", nil) } dsInstanceSettings, err := adapters.ModelToInstanceSettings(ds, hs.decryptSecureJsonDataFn(c.Req.Context())) diff --git a/pkg/api/docs/definitions/datasources.go b/pkg/api/docs/definitions/datasources.go index e911644d0bb..bf151de4a5e 100644 --- a/pkg/api/docs/definitions/datasources.go +++ b/pkg/api/docs/definitions/datasources.go @@ -126,6 +126,60 @@ import ( // 404: notFoundError // 500: internalServerError +// swagger:route GET /datasources/{datasource_id}/health datasources checkDatasourceHealthByID +// +// Check data source health by Id. +// +// Please refer to [updated API](#/datasources/checkDatasourceHealth) instead +// +// Deprecated: true +// +// Responses: +// 200: okResponse +// 400: badRequestError +// 401: unauthorisedError +// 403: forbiddenError +// 500: internalServerError + +// swagger:route GET /datasources/uid/{datasource_uid}/health datasources checkDatasourceHealth +// +// Check data source health by Id. +// +// Responses: +// 200: okResponse +// 400: badRequestError +// 401: unauthorisedError +// 403: forbiddenError +// 500: internalServerError + +// swagger:route GET /datasources/{datasource_id}/resources/{datasource_proxy_route} datasources fetchDatasourceResourcesByID +// +// Fetch data source resources by Id. +// +// Please refer to [updated API](#/datasources/fetchDatasourceResources) instead +// +// Deprecated: true +// +// Responses: +// 200: okResponse +// 400: badRequestError +// 401: unauthorisedError +// 403: forbiddenError +// 404: notFoundError +// 500: internalServerError + +// swagger:route GET /datasources/uid/{datasource_uid}/resources/{datasource_proxy_route} datasources fetchDatasourceResources +// +// Fetch data source resources. +// +// Responses: +// 200: okResponse +// 400: badRequestError +// 401: unauthorisedError +// 403: forbiddenError +// 404: notFoundError +// 500: internalServerError + // swagger:route GET /datasources/name/{datasource_name} datasources getDatasourceByName // // Get a single data source by Name. @@ -264,6 +318,7 @@ import ( // swagger:parameters updateDatasource deleteDatasourceByID getDatasourceByID datasourceProxyGETcalls datasourceProxyPOSTcalls datasourceProxyDELETEcalls // swagger:parameters enablePermissions disablePermissions getPermissions deletePermissions +// swagger:parameters checkDatasourceHealthByID fetchDatasourceResourcesByID type DatasourceID struct { // in:path // required:true @@ -271,6 +326,7 @@ type DatasourceID struct { } // swagger:parameters deleteDatasourceByUID getDatasourceByUID datasourceProxyGETByUIDcalls datasourceProxyPOSTByUIDcalls datasourceProxyDELETEByUIDcalls +// swagger:parameters checkDatasourceHealth fetchDatasourceResources type DatasourceUID struct { // in:path // required:true @@ -286,6 +342,7 @@ type DatasourceName struct { // swagger:parameters datasourceProxyGETcalls datasourceProxyPOSTcalls datasourceProxyDELETEcalls datasourceProxyGETByUIDcalls // swagger:parameters datasourceProxyPOSTByUIDcalls datasourceProxyDELETEByUIDcalls +// swagger:parameters fetchDatasourceResources fetchDatasourceResourcesByID type DatasourceProxyRouteParam struct { // in:path // required:true diff --git a/public/api-merged.json b/public/api-merged.json index 8fdfe554c47..a403a40909e 100644 --- a/public/api-merged.json +++ b/public/api-merged.json @@ -3192,6 +3192,22 @@ } }, "/annotations/{annotation_id}": { + "get": { + "tags": ["annotations"], + "summary": "Get Annotation by Id.", + "operationId": "getAnnotation", + "responses": { + "200": { + "$ref": "#/responses/getAnnotationResponse" + }, + "401": { + "$ref": "#/responses/unauthorisedError" + }, + "500": { + "$ref": "#/responses/internalServerError" + } + } + }, "put": { "description": "Updates all properties of an annotation that matches the specified id. To only update certain property, consider using the Patch Annotation operation.", "tags": ["annotations"], @@ -3992,6 +4008,98 @@ } } }, + "/dashboards/uid/{uid}/restore": { + "post": { + "tags": ["dashboard_versions"], + "summary": "Restore a dashboard to a given dashboard version using UID.", + "operationId": "restoreDashboardVersionByUID", + "parameters": [ + { + "type": "string", + "x-go-name": "UID", + "name": "uid", + "in": "path", + "required": true + }, + { + "name": "Body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/RestoreDashboardVersionCommand" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/postDashboardResponse" + }, + "401": { + "$ref": "#/responses/unauthorisedError" + }, + "403": { + "$ref": "#/responses/forbiddenError" + }, + "404": { + "$ref": "#/responses/notFoundError" + }, + "500": { + "$ref": "#/responses/internalServerError" + } + } + } + }, + "/dashboards/uid/{uid}/versions": { + "get": { + "tags": ["dashboard_versions"], + "summary": "Gets all existing versions for the dashboard using UID.", + "operationId": "getDashboardVersionsByUID", + "parameters": [ + { + "type": "string", + "x-go-name": "UID", + "name": "uid", + "in": "path", + "required": true + }, + { + "type": "integer", + "format": "int64", + "default": 0, + "x-go-name": "Limit", + "description": "Maximum number of results to return", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "format": "int64", + "default": 0, + "x-go-name": "Start", + "description": "Version to start from when returning queries", + "name": "start", + "in": "query" + } + ], + "responses": { + "200": { + "$ref": "#/responses/dashboardVersionsResponse" + }, + "401": { + "$ref": "#/responses/unauthorisedError" + }, + "403": { + "$ref": "#/responses/forbiddenError" + }, + "404": { + "$ref": "#/responses/notFoundError" + }, + "500": { + "$ref": "#/responses/internalServerError" + } + } + } + }, "/dashboards/uid/{uid}/versions/{DashboardVersionID}": { "get": { "tags": ["dashboard_versions"], @@ -4523,6 +4631,82 @@ } } }, + "/datasources/uid/{datasource_uid}/health": { + "get": { + "tags": ["datasources"], + "summary": "Check data source health by Id.", + "operationId": "checkDatasourceHealth", + "parameters": [ + { + "type": "string", + "x-go-name": "DatasourceUID", + "name": "datasource_uid", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "$ref": "#/responses/okResponse" + }, + "400": { + "$ref": "#/responses/badRequestError" + }, + "401": { + "$ref": "#/responses/unauthorisedError" + }, + "403": { + "$ref": "#/responses/forbiddenError" + }, + "500": { + "$ref": "#/responses/internalServerError" + } + } + } + }, + "/datasources/uid/{datasource_uid}/resources/{datasource_proxy_route}": { + "get": { + "tags": ["datasources"], + "summary": "Fetch data source resources.", + "operationId": "fetchDatasourceResources", + "parameters": [ + { + "type": "string", + "x-go-name": "DatasourceUID", + "name": "datasource_uid", + "in": "path", + "required": true + }, + { + "type": "string", + "x-go-name": "DatasourceProxyRoute", + "name": "datasource_proxy_route", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "$ref": "#/responses/okResponse" + }, + "400": { + "$ref": "#/responses/badRequestError" + }, + "401": { + "$ref": "#/responses/unauthorisedError" + }, + "403": { + "$ref": "#/responses/forbiddenError" + }, + "404": { + "$ref": "#/responses/notFoundError" + }, + "500": { + "$ref": "#/responses/internalServerError" + } + } + } + }, "/datasources/{datasource_id}": { "get": { "description": "If you are running Grafana Enterprise and have Fine-grained access control enabled\nyou need to have a permission with action: `datasources:read` and scopes: `datasources:*`, `datasources:uid:*` and `datasources:uid:1` (single data source).", @@ -4703,6 +4887,41 @@ } } }, + "/datasources/{datasource_id}/health": { + "get": { + "description": "Please refer to [updated API](#/datasources/checkDatasourceHealth) instead", + "tags": ["datasources"], + "summary": "Check data source health by Id.", + "operationId": "checkDatasourceHealthByID", + "deprecated": true, + "parameters": [ + { + "type": "string", + "x-go-name": "DatasourceID", + "name": "datasource_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "$ref": "#/responses/okResponse" + }, + "400": { + "$ref": "#/responses/badRequestError" + }, + "401": { + "$ref": "#/responses/unauthorisedError" + }, + "403": { + "$ref": "#/responses/forbiddenError" + }, + "500": { + "$ref": "#/responses/internalServerError" + } + } + } + }, "/datasources/{datasource_id}/permissions": { "get": { "description": "Gets all existing permissions for the data source with the given id.\n\nYou need to have a permission with action `datasources.permissions:read` and scopes `datasources:*`, `datasources:id:*`, `datasources:id:1` (single data source).", @@ -4746,15 +4965,15 @@ "parameters": [ { "type": "string", - "x-go-name": "DatasourceID", - "name": "datasource_id", + "x-go-name": "PermissionID", + "name": "permissionId", "in": "path", "required": true }, { "type": "string", - "x-go-name": "PermissionID", - "name": "permissionId", + "x-go-name": "DatasourceID", + "name": "datasource_id", "in": "path", "required": true } @@ -4778,6 +4997,51 @@ } } }, + "/datasources/{datasource_id}/resources/{datasource_proxy_route}": { + "get": { + "description": "Please refer to [updated API](#/datasources/fetchDatasourceResources) instead", + "tags": ["datasources"], + "summary": "Fetch data source resources by Id.", + "operationId": "fetchDatasourceResourcesByID", + "deprecated": true, + "parameters": [ + { + "type": "string", + "x-go-name": "DatasourceID", + "name": "datasource_id", + "in": "path", + "required": true + }, + { + "type": "string", + "x-go-name": "DatasourceProxyRoute", + "name": "datasource_proxy_route", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "$ref": "#/responses/okResponse" + }, + "400": { + "$ref": "#/responses/badRequestError" + }, + "401": { + "$ref": "#/responses/unauthorisedError" + }, + "403": { + "$ref": "#/responses/forbiddenError" + }, + "404": { + "$ref": "#/responses/notFoundError" + }, + "500": { + "$ref": "#/responses/internalServerError" + } + } + } + }, "/ds/query": { "post": { "description": "If you are running Grafana Enterprise and have Fine-grained access control enabled\nyou need to have a permission with action: `datasources:query`.", @@ -6742,32 +7006,6 @@ } } }, - "put": { - "consumes": ["application/json"], - "tags": ["provisioning"], - "summary": "Update an existing contact point.", - "operationId": "RoutePutContactpoints", - "parameters": [ - { - "name": "Body", - "in": "body", - "schema": { - "$ref": "#/definitions/EmbeddedContactPoint" - } - } - ], - "responses": { - "202": { - "$ref": "#/responses/Accepted" - }, - "400": { - "description": "ValidationError", - "schema": { - "$ref": "#/definitions/ValidationError" - } - } - } - }, "post": { "consumes": ["application/json"], "tags": ["provisioning"], @@ -6796,6 +7034,32 @@ } }, "/provisioning/contact-points/{ID}": { + "put": { + "consumes": ["application/json"], + "tags": ["provisioning"], + "summary": "Update an existing contact point.", + "operationId": "RoutePutContactpoint", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/EmbeddedContactPoint" + } + } + ], + "responses": { + "202": { + "$ref": "#/responses/Accepted" + }, + "400": { + "description": "ValidationError", + "schema": { + "$ref": "#/definitions/ValidationError" + } + } + } + }, "delete": { "consumes": ["application/json"], "tags": ["provisioning"], @@ -6814,6 +7078,42 @@ } } }, + "/provisioning/mute-timings": { + "get": { + "tags": ["provisioning"], + "summary": "Get all the mute timings.", + "operationId": "RouteGetMuteTimings", + "responses": { + "200": { + "$ref": "#/responses/MuteTiming" + }, + "400": { + "description": "ValidationError", + "schema": { + "$ref": "#/definitions/ValidationError" + } + } + } + } + }, + "/provisioning/mute-timings/{name}": { + "get": { + "tags": ["provisioning"], + "summary": "Get a mute timing.", + "operationId": "RouteGetMuteTiming", + "responses": { + "200": { + "$ref": "#/responses/MuteTiming" + }, + "400": { + "description": "ValidationError", + "schema": { + "$ref": "#/definitions/ValidationError" + } + } + } + } + }, "/provisioning/policies": { "get": { "tags": ["provisioning"], @@ -6834,11 +7134,11 @@ } } }, - "post": { + "put": { "consumes": ["application/json"], "tags": ["provisioning"], "summary": "Sets the notification policy tree.", - "operationId": "RoutePostPolicyTree", + "operationId": "RoutePutPolicyTree", "parameters": [ { "name": "Body", @@ -6879,7 +7179,7 @@ } } }, - "/provisioning/templates/{ID}": { + "/provisioning/templates/{name}": { "get": { "tags": ["provisioning"], "summary": "Get a message template.", @@ -6892,6 +7192,42 @@ "$ref": "#/responses/NotFound" } } + }, + "put": { + "consumes": ["application/json"], + "tags": ["provisioning"], + "summary": "Updates an existing template.", + "operationId": "RoutePutTemplate", + "parameters": [ + { + "name": "Body", + "in": "body", + "schema": { + "$ref": "#/definitions/MessageTemplateContent" + } + } + ], + "responses": { + "202": { + "$ref": "#/responses/Accepted" + }, + "400": { + "description": "ValidationError", + "schema": { + "$ref": "#/definitions/ValidationError" + } + } + } + }, + "delete": { + "tags": ["provisioning"], + "summary": "Delete a template.", + "operationId": "RouteDeleteTemplate", + "responses": { + "204": { + "$ref": "#/responses/Accepted" + } + } } }, "/recording-rules": { @@ -10964,7 +11300,7 @@ "format": "int64", "x-go-name": "FolderID" }, - "folderUID": { + "folderUid": { "description": "UID of the folder where the library element is stored.", "type": "string", "x-go-name": "FolderUID" @@ -11376,6 +11712,10 @@ "type": "boolean", "x-go-name": "IsHome" }, + "isPublic": { + "type": "boolean", + "x-go-name": "IsPublic" + }, "isSnapshot": { "type": "boolean", "x-go-name": "IsSnapshot" @@ -11576,6 +11916,10 @@ "format": "int64", "x-go-name": "DashboardId" }, + "dashboardUid": { + "type": "string", + "x-go-name": "DashboardUID" + }, "id": { "type": "integer", "format": "int64", @@ -11643,6 +11987,10 @@ "format": "int64", "x-go-name": "RestoredFrom" }, + "uid": { + "type": "string", + "x-go-name": "DashboardUID" + }, "version": { "type": "integer", "format": "int64", @@ -13379,7 +13727,7 @@ "format": "int64", "x-go-name": "FolderID" }, - "folderUID": { + "folderUid": { "type": "string", "x-go-name": "FolderUID" }, @@ -13592,6 +13940,15 @@ "$ref": "#/definitions/Matcher" } }, + "MessageTemplateContent": { + "type": "object", + "properties": { + "Template": { + "type": "string" + } + }, + "x-go-package": "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions" + }, "Metadata": { "description": "Metadata contains user accesses for a given resource\nEx: map[string]bool{\"create\":true, \"delete\": true}", "type": "object", @@ -14170,7 +14527,7 @@ "format": "int64", "x-go-name": "FolderID" }, - "folderUID": { + "folderUid": { "description": "UID of the folder where the library element is stored.", "type": "string", "x-go-name": "FolderUID" @@ -14807,7 +15164,7 @@ "x-go-name": "HomeTab" } }, - "x-go-package": "github.com/grafana/grafana/pkg/models" + "x-go-package": "github.com/grafana/grafana/pkg/services/preference" }, "Receiver": { "type": "object", @@ -17494,6 +17851,7 @@ "$ref": "#/definitions/Duration" }, "gettableAlert": { + "description": "GettableAlert gettable alert", "type": "object", "required": ["labels", "annotations", "endsAt", "fingerprint", "receivers", "startsAt", "status", "updatedAt"], "properties": { @@ -17543,9 +17901,7 @@ "format": "date-time", "x-go-name": "UpdatedAt" } - }, - "x-go-name": "GettableAlert", - "x-go-package": "github.com/prometheus/alertmanager/api/v2/models" + } }, "gettableAlerts": { "type": "array", @@ -17556,7 +17912,6 @@ "x-go-package": "github.com/prometheus/alertmanager/api/v2/models" }, "gettableSilence": { - "description": "GettableSilence gettable silence", "type": "object", "required": ["comment", "createdBy", "endsAt", "matchers", "startsAt", "id", "status", "updatedAt"], "properties": { @@ -17599,7 +17954,9 @@ "format": "date-time", "x-go-name": "UpdatedAt" } - } + }, + "x-go-name": "GettableSilence", + "x-go-package": "github.com/prometheus/alertmanager/api/v2/models" }, "gettableSilences": { "type": "array", @@ -17727,6 +18084,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": { @@ -17760,9 +18118,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", @@ -18268,6 +18624,12 @@ } } }, + "getAnnotationResponse": { + "description": "", + "schema": { + "$ref": "#/definitions/ItemDTO" + } + }, "getAnnotationTagsResponse": { "description": "", "schema": { diff --git a/public/api-spec.json b/public/api-spec.json index b86745df32e..e8fec990edd 100644 --- a/public/api-spec.json +++ b/public/api-spec.json @@ -2254,6 +2254,22 @@ } }, "/annotations/{annotation_id}": { + "get": { + "tags": ["annotations"], + "summary": "Get Annotation by Id.", + "operationId": "getAnnotation", + "responses": { + "200": { + "$ref": "#/responses/getAnnotationResponse" + }, + "401": { + "$ref": "#/responses/unauthorisedError" + }, + "500": { + "$ref": "#/responses/internalServerError" + } + } + }, "put": { "description": "Updates all properties of an annotation that matches the specified id. To only update certain property, consider using the Patch Annotation operation.", "tags": ["annotations"], @@ -3099,7 +3115,51 @@ "get": { "tags": ["dashboard_versions"], "summary": "Gets all existing versions for the dashboard using UID.", - "operationId": "getDashboardVersionsByUID" + "operationId": "getDashboardVersionsByUID", + "parameters": [ + { + "type": "string", + "x-go-name": "UID", + "name": "uid", + "in": "path", + "required": true + }, + { + "type": "integer", + "format": "int64", + "default": 0, + "x-go-name": "Limit", + "description": "Maximum number of results to return", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "format": "int64", + "default": 0, + "x-go-name": "Start", + "description": "Version to start from when returning queries", + "name": "start", + "in": "query" + } + ], + "responses": { + "200": { + "$ref": "#/responses/dashboardVersionsResponse" + }, + "401": { + "$ref": "#/responses/unauthorisedError" + }, + "403": { + "$ref": "#/responses/forbiddenError" + }, + "404": { + "$ref": "#/responses/notFoundError" + }, + "500": { + "$ref": "#/responses/internalServerError" + } + } } }, "/dashboards/uid/{uid}/versions/{DashboardVersionID}": { @@ -3633,6 +3693,82 @@ } } }, + "/datasources/uid/{datasource_uid}/health": { + "get": { + "tags": ["datasources"], + "summary": "Check data source health by Id.", + "operationId": "checkDatasourceHealth", + "parameters": [ + { + "type": "string", + "x-go-name": "DatasourceUID", + "name": "datasource_uid", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "$ref": "#/responses/okResponse" + }, + "400": { + "$ref": "#/responses/badRequestError" + }, + "401": { + "$ref": "#/responses/unauthorisedError" + }, + "403": { + "$ref": "#/responses/forbiddenError" + }, + "500": { + "$ref": "#/responses/internalServerError" + } + } + } + }, + "/datasources/uid/{datasource_uid}/resources/{datasource_proxy_route}": { + "get": { + "tags": ["datasources"], + "summary": "Fetch data source resources.", + "operationId": "fetchDatasourceResources", + "parameters": [ + { + "type": "string", + "x-go-name": "DatasourceUID", + "name": "datasource_uid", + "in": "path", + "required": true + }, + { + "type": "string", + "x-go-name": "DatasourceProxyRoute", + "name": "datasource_proxy_route", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "$ref": "#/responses/okResponse" + }, + "400": { + "$ref": "#/responses/badRequestError" + }, + "401": { + "$ref": "#/responses/unauthorisedError" + }, + "403": { + "$ref": "#/responses/forbiddenError" + }, + "404": { + "$ref": "#/responses/notFoundError" + }, + "500": { + "$ref": "#/responses/internalServerError" + } + } + } + }, "/datasources/{datasource_id}": { "get": { "description": "If you are running Grafana Enterprise and have Fine-grained access control enabled\nyou need to have a permission with action: `datasources:read` and scopes: `datasources:*`, `datasources:uid:*` and `datasources:uid:1` (single data source).", @@ -3813,6 +3949,41 @@ } } }, + "/datasources/{datasource_id}/health": { + "get": { + "description": "Please refer to [updated API](#/datasources/checkDatasourceHealth) instead", + "tags": ["datasources"], + "summary": "Check data source health by Id.", + "operationId": "checkDatasourceHealthByID", + "deprecated": true, + "parameters": [ + { + "type": "string", + "x-go-name": "DatasourceID", + "name": "datasource_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "$ref": "#/responses/okResponse" + }, + "400": { + "$ref": "#/responses/badRequestError" + }, + "401": { + "$ref": "#/responses/unauthorisedError" + }, + "403": { + "$ref": "#/responses/forbiddenError" + }, + "500": { + "$ref": "#/responses/internalServerError" + } + } + } + }, "/datasources/{datasource_id}/permissions": { "get": { "description": "Gets all existing permissions for the data source with the given id.\n\nYou need to have a permission with action `datasources.permissions:read` and scopes `datasources:*`, `datasources:id:*`, `datasources:id:1` (single data source).", @@ -3856,15 +4027,15 @@ "parameters": [ { "type": "string", - "x-go-name": "DatasourceID", - "name": "datasource_id", + "x-go-name": "PermissionID", + "name": "permissionId", "in": "path", "required": true }, { "type": "string", - "x-go-name": "PermissionID", - "name": "permissionId", + "x-go-name": "DatasourceID", + "name": "datasource_id", "in": "path", "required": true } @@ -3888,6 +4059,51 @@ } } }, + "/datasources/{datasource_id}/resources/{datasource_proxy_route}": { + "get": { + "description": "Please refer to [updated API](#/datasources/fetchDatasourceResources) instead", + "tags": ["datasources"], + "summary": "Fetch data source resources by Id.", + "operationId": "fetchDatasourceResourcesByID", + "deprecated": true, + "parameters": [ + { + "type": "string", + "x-go-name": "DatasourceID", + "name": "datasource_id", + "in": "path", + "required": true + }, + { + "type": "string", + "x-go-name": "DatasourceProxyRoute", + "name": "datasource_proxy_route", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "$ref": "#/responses/okResponse" + }, + "400": { + "$ref": "#/responses/badRequestError" + }, + "401": { + "$ref": "#/responses/unauthorisedError" + }, + "403": { + "$ref": "#/responses/forbiddenError" + }, + "404": { + "$ref": "#/responses/notFoundError" + }, + "500": { + "$ref": "#/responses/internalServerError" + } + } + } + }, "/ds/query": { "post": { "description": "If you are running Grafana Enterprise and have Fine-grained access control enabled\nyou need to have a permission with action: `datasources:query`.", @@ -9008,7 +9224,7 @@ "format": "int64", "x-go-name": "FolderID" }, - "folderUID": { + "folderUid": { "description": "UID of the folder where the library element is stored.", "type": "string", "x-go-name": "FolderUID" @@ -9420,6 +9636,10 @@ "type": "boolean", "x-go-name": "IsHome" }, + "isPublic": { + "type": "boolean", + "x-go-name": "IsPublic" + }, "isSnapshot": { "type": "boolean", "x-go-name": "IsSnapshot" @@ -9620,6 +9840,10 @@ "format": "int64", "x-go-name": "DashboardId" }, + "dashboardUid": { + "type": "string", + "x-go-name": "DashboardUID" + }, "id": { "type": "integer", "format": "int64", @@ -9687,6 +9911,10 @@ "format": "int64", "x-go-name": "RestoredFrom" }, + "uid": { + "type": "string", + "x-go-name": "DashboardUID" + }, "version": { "type": "integer", "format": "int64", @@ -10600,7 +10828,7 @@ "format": "int64", "x-go-name": "FolderID" }, - "folderUID": { + "folderUid": { "type": "string", "x-go-name": "FolderUID" }, @@ -11049,7 +11277,7 @@ "format": "int64", "x-go-name": "FolderID" }, - "folderUID": { + "folderUid": { "description": "UID of the folder where the library element is stored.", "type": "string", "x-go-name": "FolderUID" @@ -11313,7 +11541,7 @@ "x-go-name": "HomeTab" } }, - "x-go-package": "github.com/grafana/grafana/pkg/models" + "x-go-package": "github.com/grafana/grafana/pkg/services/preference" }, "RecordingRuleJSON": { "description": "RecordingRuleJSON is the external representation of a recording rule", @@ -13239,6 +13467,12 @@ } } }, + "getAnnotationResponse": { + "description": "", + "schema": { + "$ref": "#/definitions/ItemDTO" + } + }, "getAnnotationTagsResponse": { "description": "", "schema": {