[v8.5.x] Backport 48550 to v8.5.x (#48656)

* resolve conflicts

* update swagger docs
This commit is contained in:
Will Browne
2022-05-03 20:58:02 +02:00
committed by GitHub
parent 633d598fcd
commit 7f7803ba59
11 changed files with 512 additions and 139 deletions
+10
View File
@@ -691,6 +691,16 @@ In addition, specific properties of each data source should be added in a reques
}
```
#### Status codes
| Code | Description |
| ---- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 200 | All data source queries returned a successful response. |
| 400 | Bad request due to invalid JSON, missing content type, missing or invalid fields, etc. Or one or more data source queries were unsuccessful. Refer to the body for more details. |
| 403 | Access denied. |
| 404 | Either the data source or plugin required to fulfil the request could not be found. |
| 500 | Unexpected error. Refer to the body and/or server logs for more details. |
## Deprecated resources
The following resources have been deprecated. They will be removed in a future release.
@@ -55,4 +55,5 @@ export interface FeatureToggles {
explore2Dashboard?: boolean;
tracing?: boolean;
persistNotifications?: boolean;
datasourceQueryMultiStatus?: boolean;
}
+1
View File
@@ -14,6 +14,7 @@ import (
//
// Responses:
// 200: queryDataResponse
// 207: queryDataResponse
// 401: unauthorisedError
// 400: badRequestError
// 403: forbiddenError
+9 -4
View File
@@ -31,7 +31,7 @@ func (hs *HTTPServer) QueryMetricsV2(c *models.ReqContext) response.Response {
if err != nil {
return hs.handleQueryMetricsError(err)
}
return toJsonStreamingResponse(resp)
return hs.toJsonStreamingResponse(resp)
}
func (hs *HTTPServer) handleQueryMetricsError(err error) *response.NormalResponse {
@@ -147,7 +147,7 @@ func (hs *HTTPServer) QueryMetricsFromDashboard(c *models.ReqContext) response.R
if err != nil {
return hs.handleQueryMetricsError(err)
}
return toJsonStreamingResponse(resp)
return hs.toJsonStreamingResponse(resp)
}
// QueryMetrics returns query metrics
@@ -198,11 +198,16 @@ func (hs *HTTPServer) QueryMetrics(c *models.ReqContext) response.Response {
return response.JSON(statusCode, &legacyResp)
}
func toJsonStreamingResponse(qdr *backend.QueryDataResponse) response.Response {
func (hs *HTTPServer) toJsonStreamingResponse(qdr *backend.QueryDataResponse) response.Response {
statusWhenError := http.StatusBadRequest
if hs.Features.IsEnabled(featuremgmt.FlagDatasourceQueryMultiStatus) {
statusWhenError = http.StatusMultiStatus
}
statusCode := http.StatusOK
for _, res := range qdr.Responses {
if res.Error != nil {
statusCode = http.StatusBadRequest
statusCode = statusWhenError
}
}
+50
View File
@@ -11,6 +11,7 @@ import (
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/services/sqlstore/mockstore"
"github.com/grafana/grafana/pkg/web/webtest"
"golang.org/x/oauth2"
@@ -21,6 +22,7 @@ import (
"github.com/grafana/grafana/pkg/services/query"
"github.com/grafana/grafana/pkg/services/secrets/fakes"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
var (
@@ -492,3 +494,51 @@ func TestAPIEndpoint_Metrics_ParseDashboardQueryParams(t *testing.T) {
})
}
}
// `/ds/query` endpoint test
func TestAPIEndpoint_Metrics_QueryMetricsV2(t *testing.T) {
qds := query.ProvideService(
nil,
nil,
nil,
&fakePluginRequestValidator{},
fakes.NewFakeSecretsService(),
&fakePluginClient{
QueryDataHandlerFunc: func(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
resp := backend.Responses{
"A": backend.DataResponse{
Error: fmt.Errorf("query failed"),
},
}
return &backend.QueryDataResponse{Responses: resp}, nil
},
},
&fakeOAuthTokenService{},
)
serverFeatureEnabled := SetupAPITestServer(t, func(hs *HTTPServer) {
hs.queryDataService = qds
hs.Features = featuremgmt.WithFeatures(featuremgmt.FlagDatasourceQueryMultiStatus, true)
})
serverFeatureDisabled := SetupAPITestServer(t, func(hs *HTTPServer) {
hs.queryDataService = qds
hs.Features = featuremgmt.WithFeatures(featuremgmt.FlagDatasourceQueryMultiStatus, false)
})
t.Run("Status code is 400 when data source response has an error and feature toggle is disabled", func(t *testing.T) {
req := serverFeatureDisabled.NewPostRequest("/api/ds/query", strings.NewReader(queryDatasourceInput))
webtest.RequestWithSignedInUser(req, &models.SignedInUser{UserId: 1, OrgId: 1, OrgRole: models.ROLE_VIEWER})
resp, err := serverFeatureDisabled.SendJSON(req)
require.NoError(t, err)
require.NoError(t, resp.Body.Close())
require.Equal(t, http.StatusBadRequest, resp.StatusCode)
})
t.Run("Status code is 207 when data source response has an error and feature toggle is enabled", func(t *testing.T) {
req := serverFeatureEnabled.NewPostRequest("/api/ds/query", strings.NewReader(queryDatasourceInput))
webtest.RequestWithSignedInUser(req, &models.SignedInUser{UserId: 1, OrgId: 1, OrgRole: models.ROLE_VIEWER})
resp, err := serverFeatureEnabled.SendJSON(req)
require.NoError(t, err)
require.NoError(t, resp.Body.Close())
require.Equal(t, http.StatusMultiStatus, resp.StatusCode)
})
}
+11 -1
View File
@@ -249,9 +249,11 @@ type fakePluginClient struct {
plugins.Client
req *backend.CallResourceRequest
backend.QueryDataHandlerFunc
}
func (c *fakePluginClient) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
func (c *fakePluginClient) CallResource(_ context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
c.req = req
bytes, err := json.Marshal(map[string]interface{}{
"message": "hello",
@@ -266,3 +268,11 @@ func (c *fakePluginClient) CallResource(ctx context.Context, req *backend.CallRe
Body: bytes,
})
}
func (c *fakePluginClient) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
if c.QueryDataHandlerFunc != nil {
return c.QueryDataHandlerFunc.QueryData(ctx, req)
}
return backend.NewQueryDataResponse(), nil
}
+5
View File
@@ -219,5 +219,10 @@ var (
State: FeatureStateAlpha,
FrontendOnly: true,
},
{
Name: "datasourceQueryMultiStatus",
Description: "Introduce HTTP 207 Multi Status for api/ds/query",
State: FeatureStateAlpha,
},
}
)
+4
View File
@@ -162,4 +162,8 @@ const (
// FlagPersistNotifications
// PoC Notifications page
FlagPersistNotifications = "persistNotifications"
// FlagDatasourceQueryMultiStatus
// Introduce HTTP 207 Multi Status for api/ds/query
FlagDatasourceQueryMultiStatus = "datasourceQueryMultiStatus"
)
+312 -71
View File
@@ -1025,7 +1025,7 @@
"basic": []
}
],
"description": "If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users:delete` and scope `global:users:*`.",
"description": "If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users:delete` and scope `global.users:*`.",
"tags": ["admin_users"],
"summary": "Delete global User.",
"operationId": "deleteUser",
@@ -1065,7 +1065,7 @@
"basic": []
}
],
"description": "If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users.authtoken:list` and scope `global:users:*`.",
"description": "If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users.authtoken:list` and scope `global.users:*`.",
"tags": ["admin_users"],
"summary": "Return a list of all auth tokens (devices) that the user currently have logged in from.",
"operationId": "getAuthTokens",
@@ -1102,7 +1102,7 @@
"basic": []
}
],
"description": "If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users:disable` and scope `global:users:1` (userIDScope).",
"description": "If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users:disable` and scope `global.users:1` (userIDScope).",
"tags": ["admin_users"],
"summary": "Disable user.",
"operationId": "disableUser",
@@ -1142,7 +1142,7 @@
"basic": []
}
],
"description": "If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users:enable` and scope `global:users:1` (userIDScope).",
"description": "If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users:enable` and scope `global.users:1` (userIDScope).",
"tags": ["admin_users"],
"summary": "Enable user.",
"operationId": "enableUser",
@@ -1182,7 +1182,7 @@
"basic": []
}
],
"description": "If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users.logout` and scope `global:users:*`.",
"description": "If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users.logout` and scope `global.users:*`.",
"tags": ["admin_users"],
"summary": "Logout user revokes all auth tokens (devices) for the user. User of issued auth tokens (devices) will no longer be logged in and will be required to authenticate again upon next activity.",
"operationId": "logoutUser",
@@ -1225,7 +1225,7 @@
"basic": []
}
],
"description": "If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users.password:update` and scope `global:users:*`.",
"description": "If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users.password:update` and scope `global.users:*`.",
"tags": ["admin_users"],
"summary": "Set password for user.",
"operationId": "setPassword",
@@ -1269,7 +1269,7 @@
},
"/admin/users/{user_id}/permissions": {
"put": {
"description": "Only works with Basic Authentication (username and password). See introduction for an explanation.\nIf you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users.permissions:update` and scope `global:users:*`.",
"description": "Only works with Basic Authentication (username and password). See introduction for an explanation.\nIf you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users.permissions:update` and scope `global.users:*`.",
"tags": ["admin_users"],
"summary": "Set permissions for user.",
"operationId": "setPermissions",
@@ -1318,7 +1318,7 @@
"basic": []
}
],
"description": "If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users.quotas:list` and scope `global:users:1` (userIDScope).",
"description": "If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users.quotas:list` and scope `global.users:1` (userIDScope).",
"tags": ["admin_users"],
"summary": "Fetch user quota.",
"operationId": "getUserQuota",
@@ -1358,7 +1358,7 @@
"basic": []
}
],
"description": "If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users.quotas:update` and scope `global:users:1` (userIDScope).",
"description": "If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users.quotas:update` and scope `global.users:1` (userIDScope).",
"tags": ["admin_users"],
"summary": "Update user quota.",
"operationId": "updateUserQuota",
@@ -1414,7 +1414,7 @@
"basic": []
}
],
"description": "Revokes the given auth token (device) for the user. User of issued auth token (device) will no longer be logged in and will be required to authenticate again upon next activity.\nIf you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users.authtoken:update` and scope `global:users:*`.",
"description": "Revokes the given auth token (device) for the user. User of issued auth token (device) will no longer be logged in and will be required to authenticate again upon next activity.\nIf you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users.authtoken:update` and scope `global.users:*`.",
"tags": ["admin_users"],
"summary": "Revoke auth token for user.",
"operationId": "revokeAuthToken",
@@ -3150,7 +3150,7 @@
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/DeleteAnnotationsCmd"
"$ref": "#/definitions/MassDeleteAnnotationsCmd"
}
}
],
@@ -4273,7 +4273,7 @@
},
"/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:id:*` and `datasources:id:1` (single data source).",
"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).",
"tags": ["datasources"],
"summary": "Get a single data source by Id.",
"operationId": "getDatasourceByID",
@@ -4308,7 +4308,7 @@
}
},
"put": {
"description": "Similar to creating a data source, `password` and `basicAuthPassword` should be defined under\nsecureJsonData in order to be stored securely as an encrypted blob in the database. Then, the\nencrypted fields are listed under secureJsonFields section in the response.\n\nIf you are running Grafana Enterprise and have Fine-grained access control enabled\nyou need to have a permission with action: `datasources:write` and scopes: `datasources:*`, `datasources:id:*` and `datasources:id:1` (single data source).",
"description": "Similar to creating a data source, `password` and `basicAuthPassword` should be defined under\nsecureJsonData in order to be stored securely as an encrypted blob in the database. Then, the\nencrypted fields are listed under secureJsonFields section in the response.\n\nIf you are running Grafana Enterprise and have Fine-grained access control enabled\nyou need to have a permission with action: `datasources:write` and scopes: `datasources:*`, `datasources:uid:*` and `datasources:uid:1` (single data source).",
"tags": ["datasources"],
"summary": "Update an existing data source.",
"operationId": "updateDatasource",
@@ -4345,7 +4345,7 @@
}
},
"delete": {
"description": "If you are running Grafana Enterprise and have Fine-grained access control enabled\nyou need to have a permission with action: `datasources:delete` and scopes: `datasources:*`, `datasources:id:*` and `datasources:id:1` (single data source).",
"description": "If you are running Grafana Enterprise and have Fine-grained access control enabled\nyou need to have a permission with action: `datasources:delete` and scopes: `datasources:*`, `datasources:uid:*` and `datasources:uid:1` (single data source).",
"tags": ["datasources"],
"summary": "Delete an existing data source by id.",
"operationId": "deleteDatasourceByID",
@@ -4547,6 +4547,9 @@
"200": {
"$ref": "#/responses/queryDataResponse"
},
"207": {
"$ref": "#/responses/queryDataResponse"
},
"400": {
"$ref": "#/responses/badRequestError"
},
@@ -6469,6 +6472,178 @@
}
}
},
"/provisioning/contact-points": {
"get": {
"tags": ["provisioning"],
"summary": "Get all the contact points.",
"operationId": "RouteGetContactpoints",
"responses": {
"200": {
"description": "Route",
"schema": {
"$ref": "#/definitions/Route"
}
},
"400": {
"description": "ValidationError",
"schema": {
"$ref": "#/definitions/ValidationError"
}
}
}
},
"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"],
"summary": "Create a contact point.",
"operationId": "RoutePostContactpoints",
"parameters": [
{
"name": "Body",
"in": "body",
"schema": {
"$ref": "#/definitions/EmbeddedContactPoint"
}
}
],
"responses": {
"202": {
"$ref": "#/responses/Accepted"
},
"400": {
"description": "ValidationError",
"schema": {
"$ref": "#/definitions/ValidationError"
}
}
}
}
},
"/provisioning/contact-points/{ID}": {
"delete": {
"consumes": ["application/json"],
"tags": ["provisioning"],
"summary": "Delete a contact point.",
"operationId": "RouteDeleteContactpoints",
"responses": {
"202": {
"$ref": "#/responses/Accepted"
},
"400": {
"description": "ValidationError",
"schema": {
"$ref": "#/definitions/ValidationError"
}
}
}
}
},
"/provisioning/policies": {
"get": {
"tags": ["provisioning"],
"summary": "Get the notification policy tree.",
"operationId": "RouteGetPolicyTree",
"responses": {
"200": {
"description": "Route",
"schema": {
"$ref": "#/definitions/Route"
}
},
"400": {
"description": "ValidationError",
"schema": {
"$ref": "#/definitions/ValidationError"
}
}
}
},
"post": {
"consumes": ["application/json"],
"tags": ["provisioning"],
"summary": "Sets the notification policy tree.",
"operationId": "RoutePostPolicyTree",
"parameters": [
{
"name": "Body",
"in": "body",
"schema": {
"$ref": "#/definitions/Route"
}
}
],
"responses": {
"202": {
"$ref": "#/responses/Accepted"
},
"400": {
"description": "ValidationError",
"schema": {
"$ref": "#/definitions/ValidationError"
}
}
}
}
},
"/provisioning/templates": {
"get": {
"tags": ["provisioning"],
"summary": "Get all message templates.",
"operationId": "RouteGetTemplates",
"responses": {
"200": {
"$ref": "#/responses/MessageTemplate"
},
"400": {
"description": "ValidationError",
"schema": {
"$ref": "#/definitions/ValidationError"
}
}
}
}
},
"/provisioning/templates/{ID}": {
"get": {
"tags": ["provisioning"],
"summary": "Get a message template.",
"operationId": "RouteGetTemplate",
"responses": {
"200": {
"$ref": "#/responses/MessageTemplate"
},
"404": {
"$ref": "#/responses/NotFound"
}
}
}
},
"/recording-rules": {
"get": {
"tags": ["recording_rules", "enterprise"],
@@ -7888,6 +8063,14 @@
"summary": "Add External Group.",
"operationId": "addTeamGroupApi",
"parameters": [
{
"type": "integer",
"format": "int64",
"x-go-name": "TeamID",
"name": "teamId",
"in": "path",
"required": true
},
{
"x-go-name": "Body",
"name": "body",
@@ -7896,14 +8079,6 @@
"schema": {
"$ref": "#/definitions/TeamGroupMapping"
}
},
{
"type": "integer",
"format": "int64",
"x-go-name": "TeamID",
"name": "teamId",
"in": "path",
"required": true
}
],
"responses": {
@@ -7937,16 +8112,16 @@
{
"type": "integer",
"format": "int64",
"x-go-name": "GroupID",
"name": "groupId",
"x-go-name": "TeamID",
"name": "teamId",
"in": "path",
"required": true
},
{
"type": "integer",
"format": "int64",
"x-go-name": "TeamID",
"name": "teamId",
"x-go-name": "GroupID",
"name": "groupId",
"in": "path",
"required": true
}
@@ -10122,6 +10297,36 @@
},
"x-go-package": "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
},
"AnnotationActions": {
"type": "object",
"properties": {
"canAdd": {
"type": "boolean",
"x-go-name": "CanAdd"
},
"canDelete": {
"type": "boolean",
"x-go-name": "CanDelete"
},
"canEdit": {
"type": "boolean",
"x-go-name": "CanEdit"
}
},
"x-go-package": "github.com/grafana/grafana/pkg/api/dtos"
},
"AnnotationPermission": {
"type": "object",
"properties": {
"dashboard": {
"$ref": "#/definitions/AnnotationActions"
},
"organization": {
"$ref": "#/definitions/AnnotationActions"
}
},
"x-go-package": "github.com/grafana/grafana/pkg/api/dtos"
},
"ApiKeyDTO": {
"type": "object",
"properties": {
@@ -10240,7 +10445,7 @@
"x-go-name": "ReportLogo"
}
},
"x-go-package": "github.com/grafana/grafana/pkg/extensions/report"
"x-go-package": "github.com/grafana/grafana/pkg/extensions/report/api"
},
"CalculateDiffTarget": {
"type": "object",
@@ -10390,7 +10595,7 @@
"x-go-name": "UserID"
}
},
"x-go-package": "github.com/grafana/grafana/pkg/extensions/report"
"x-go-package": "github.com/grafana/grafana/pkg/extensions/report/api"
},
"CreateAlertNotificationCommand": {
"type": "object",
@@ -10576,7 +10781,7 @@
"x-go-name": "TemplateVars"
}
},
"x-go-package": "github.com/grafana/grafana/pkg/extensions/report"
"x-go-package": "github.com/grafana/grafana/pkg/extensions/report/api"
},
"CreateOrgCommand": {
"type": "object",
@@ -10836,6 +11041,9 @@
"DashboardMeta": {
"type": "object",
"properties": {
"annotationsPermissions": {
"$ref": "#/definitions/AnnotationPermission"
},
"canAdmin": {
"type": "boolean",
"x-go-name": "CanAdmin"
@@ -11499,32 +11707,6 @@
},
"x-go-package": "github.com/prometheus/alertmanager/timeinterval"
},
"DeleteAnnotationsCmd": {
"type": "object",
"properties": {
"alertId": {
"type": "integer",
"format": "int64",
"x-go-name": "AlertId"
},
"annotationId": {
"type": "integer",
"format": "int64",
"x-go-name": "AnnotationId"
},
"dashboardId": {
"type": "integer",
"format": "int64",
"x-go-name": "DashboardId"
},
"panelId": {
"type": "integer",
"format": "int64",
"x-go-name": "PanelId"
}
},
"x-go-package": "github.com/grafana/grafana/pkg/api/dtos"
},
"DeleteTokenCommand": {
"type": "object",
"properties": {
@@ -11631,6 +11813,36 @@
},
"x-go-package": "github.com/prometheus/alertmanager/config"
},
"EmbeddedContactPoint": {
"description": "EmbeddedContactPoint is the contact point type that is used\nby grafanas embedded alertmanager implementation.",
"type": "object",
"properties": {
"disableResolveMessage": {
"type": "boolean",
"x-go-name": "DisableResolveMessage"
},
"name": {
"type": "string",
"x-go-name": "Name"
},
"provanance": {
"type": "string",
"x-go-name": "Provenance"
},
"settings": {
"$ref": "#/definitions/Json"
},
"type": {
"type": "string",
"x-go-name": "Type"
},
"uid": {
"type": "string",
"x-go-name": "UID"
}
},
"x-go-package": "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
},
"ErrorResponseBody": {
"type": "object",
"required": ["message"],
@@ -12479,18 +12691,18 @@
"x-go-name": "URL"
}
},
"x-go-package": "github.com/grafana/grafana/pkg/services/search"
"x-go-package": "github.com/grafana/grafana/pkg/models"
},
"HitList": {
"type": "array",
"items": {
"$ref": "#/definitions/Hit"
},
"x-go-package": "github.com/grafana/grafana/pkg/services/search"
"x-go-package": "github.com/grafana/grafana/pkg/models"
},
"HitType": {
"type": "string",
"x-go-package": "github.com/grafana/grafana/pkg/services/search"
"x-go-package": "github.com/grafana/grafana/pkg/models"
},
"HostPort": {
"type": "object",
@@ -13033,6 +13245,27 @@
},
"x-go-package": "github.com/grafana/grafana/pkg/services/libraryelements"
},
"MassDeleteAnnotationsCmd": {
"type": "object",
"properties": {
"annotationId": {
"type": "integer",
"format": "int64",
"x-go-name": "AnnotationId"
},
"dashboardId": {
"type": "integer",
"format": "int64",
"x-go-name": "DashboardId"
},
"panelId": {
"type": "integer",
"format": "int64",
"x-go-name": "PanelId"
}
},
"x-go-package": "github.com/grafana/grafana/pkg/api/dtos"
},
"MatchRegexps": {
"type": "object",
"title": "MatchRegexps represents a map of Regexp.",
@@ -14427,7 +14660,7 @@
"x-go-name": "UseEmailsFromReport"
}
},
"x-go-package": "github.com/grafana/grafana/pkg/extensions/report"
"x-go-package": "github.com/grafana/grafana/pkg/extensions/report/api"
},
"ReportOptionsDTO": {
"type": "object",
@@ -14444,7 +14677,7 @@
"$ref": "#/definitions/TimeRangeDTO"
}
},
"x-go-package": "github.com/grafana/grafana/pkg/extensions/report"
"x-go-package": "github.com/grafana/grafana/pkg/extensions/report/api"
},
"ResponseDetails": {
"type": "object",
@@ -14900,7 +15133,7 @@
"x-go-name": "WorkdaysOnly"
}
},
"x-go-package": "github.com/grafana/grafana/pkg/extensions/report"
"x-go-package": "github.com/grafana/grafana/pkg/extensions/report/api"
},
"SearchTeamQueryResult": {
"type": "object",
@@ -15020,7 +15253,7 @@
"x-go-name": "UserID"
}
},
"x-go-package": "github.com/grafana/grafana/pkg/extensions/report"
"x-go-package": "github.com/grafana/grafana/pkg/extensions/report/api"
},
"SigV4Config": {
"description": "SigV4Config is the configuration for signing remote write requests with\nAWS's SigV4 verification process. Empty values will be retrieved using the\nAWS default credentials chain.",
@@ -15713,7 +15946,7 @@
"x-go-name": "To"
}
},
"x-go-package": "github.com/grafana/grafana/pkg/extensions/report"
"x-go-package": "github.com/grafana/grafana/pkg/extensions/report/api"
},
"Token": {
"type": "object",
@@ -15814,6 +16047,15 @@
"format": "int64",
"x-go-name": "TokenExpiresWarnDays"
},
"trial": {
"type": "boolean",
"x-go-name": "Trial"
},
"trial_exp": {
"type": "integer",
"format": "int64",
"x-go-name": "TrialExpires"
},
"update_days": {
"type": "integer",
"format": "int64",
@@ -16792,12 +17034,11 @@
}
},
"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",
@@ -16900,7 +17141,6 @@
"$ref": "#/definitions/Duration"
},
"gettableAlert": {
"description": "GettableAlert gettable alert",
"type": "object",
"required": ["labels", "annotations", "endsAt", "fingerprint", "receivers", "startsAt", "status", "updatedAt"],
"properties": {
@@ -16950,7 +17190,9 @@
"format": "date-time",
"x-go-name": "UpdatedAt"
}
}
},
"x-go-name": "GettableAlert",
"x-go-package": "github.com/prometheus/alertmanager/api/v2/models"
},
"gettableAlerts": {
"description": "GettableAlerts gettable alerts",
@@ -17006,12 +17248,11 @@
}
},
"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",
+103 -63
View File
@@ -1025,7 +1025,7 @@
"basic": []
}
],
"description": "If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users:delete` and scope `global:users:*`.",
"description": "If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users:delete` and scope `global.users:*`.",
"tags": ["admin_users"],
"summary": "Delete global User.",
"operationId": "deleteUser",
@@ -1065,7 +1065,7 @@
"basic": []
}
],
"description": "If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users.authtoken:list` and scope `global:users:*`.",
"description": "If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users.authtoken:list` and scope `global.users:*`.",
"tags": ["admin_users"],
"summary": "Return a list of all auth tokens (devices) that the user currently have logged in from.",
"operationId": "getAuthTokens",
@@ -1102,7 +1102,7 @@
"basic": []
}
],
"description": "If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users:disable` and scope `global:users:1` (userIDScope).",
"description": "If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users:disable` and scope `global.users:1` (userIDScope).",
"tags": ["admin_users"],
"summary": "Disable user.",
"operationId": "disableUser",
@@ -1142,7 +1142,7 @@
"basic": []
}
],
"description": "If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users:enable` and scope `global:users:1` (userIDScope).",
"description": "If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users:enable` and scope `global.users:1` (userIDScope).",
"tags": ["admin_users"],
"summary": "Enable user.",
"operationId": "enableUser",
@@ -1182,7 +1182,7 @@
"basic": []
}
],
"description": "If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users.logout` and scope `global:users:*`.",
"description": "If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users.logout` and scope `global.users:*`.",
"tags": ["admin_users"],
"summary": "Logout user revokes all auth tokens (devices) for the user. User of issued auth tokens (devices) will no longer be logged in and will be required to authenticate again upon next activity.",
"operationId": "logoutUser",
@@ -1225,7 +1225,7 @@
"basic": []
}
],
"description": "If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users.password:update` and scope `global:users:*`.",
"description": "If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users.password:update` and scope `global.users:*`.",
"tags": ["admin_users"],
"summary": "Set password for user.",
"operationId": "setPassword",
@@ -1269,7 +1269,7 @@
},
"/admin/users/{user_id}/permissions": {
"put": {
"description": "Only works with Basic Authentication (username and password). See introduction for an explanation.\nIf you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users.permissions:update` and scope `global:users:*`.",
"description": "Only works with Basic Authentication (username and password). See introduction for an explanation.\nIf you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users.permissions:update` and scope `global.users:*`.",
"tags": ["admin_users"],
"summary": "Set permissions for user.",
"operationId": "setPermissions",
@@ -1318,7 +1318,7 @@
"basic": []
}
],
"description": "If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users.quotas:list` and scope `global:users:1` (userIDScope).",
"description": "If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users.quotas:list` and scope `global.users:1` (userIDScope).",
"tags": ["admin_users"],
"summary": "Fetch user quota.",
"operationId": "getUserQuota",
@@ -1358,7 +1358,7 @@
"basic": []
}
],
"description": "If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users.quotas:update` and scope `global:users:1` (userIDScope).",
"description": "If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users.quotas:update` and scope `global.users:1` (userIDScope).",
"tags": ["admin_users"],
"summary": "Update user quota.",
"operationId": "updateUserQuota",
@@ -1414,7 +1414,7 @@
"basic": []
}
],
"description": "Revokes the given auth token (device) for the user. User of issued auth token (device) will no longer be logged in and will be required to authenticate again upon next activity.\nIf you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users.authtoken:update` and scope `global:users:*`.",
"description": "Revokes the given auth token (device) for the user. User of issued auth token (device) will no longer be logged in and will be required to authenticate again upon next activity.\nIf you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users.authtoken:update` and scope `global.users:*`.",
"tags": ["admin_users"],
"summary": "Revoke auth token for user.",
"operationId": "revokeAuthToken",
@@ -2200,7 +2200,7 @@
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/DeleteAnnotationsCmd"
"$ref": "#/definitions/MassDeleteAnnotationsCmd"
}
}
],
@@ -3323,7 +3323,7 @@
},
"/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:id:*` and `datasources:id:1` (single data source).",
"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).",
"tags": ["datasources"],
"summary": "Get a single data source by Id.",
"operationId": "getDatasourceByID",
@@ -3358,7 +3358,7 @@
}
},
"put": {
"description": "Similar to creating a data source, `password` and `basicAuthPassword` should be defined under\nsecureJsonData in order to be stored securely as an encrypted blob in the database. Then, the\nencrypted fields are listed under secureJsonFields section in the response.\n\nIf you are running Grafana Enterprise and have Fine-grained access control enabled\nyou need to have a permission with action: `datasources:write` and scopes: `datasources:*`, `datasources:id:*` and `datasources:id:1` (single data source).",
"description": "Similar to creating a data source, `password` and `basicAuthPassword` should be defined under\nsecureJsonData in order to be stored securely as an encrypted blob in the database. Then, the\nencrypted fields are listed under secureJsonFields section in the response.\n\nIf you are running Grafana Enterprise and have Fine-grained access control enabled\nyou need to have a permission with action: `datasources:write` and scopes: `datasources:*`, `datasources:uid:*` and `datasources:uid:1` (single data source).",
"tags": ["datasources"],
"summary": "Update an existing data source.",
"operationId": "updateDatasource",
@@ -3395,7 +3395,7 @@
}
},
"delete": {
"description": "If you are running Grafana Enterprise and have Fine-grained access control enabled\nyou need to have a permission with action: `datasources:delete` and scopes: `datasources:*`, `datasources:id:*` and `datasources:id:1` (single data source).",
"description": "If you are running Grafana Enterprise and have Fine-grained access control enabled\nyou need to have a permission with action: `datasources:delete` and scopes: `datasources:*`, `datasources:uid:*` and `datasources:uid:1` (single data source).",
"tags": ["datasources"],
"summary": "Delete an existing data source by id.",
"operationId": "deleteDatasourceByID",
@@ -3597,6 +3597,9 @@
"200": {
"$ref": "#/responses/queryDataResponse"
},
"207": {
"$ref": "#/responses/queryDataResponse"
},
"400": {
"$ref": "#/responses/badRequestError"
},
@@ -6457,6 +6460,14 @@
"summary": "Add External Group.",
"operationId": "addTeamGroupApi",
"parameters": [
{
"type": "integer",
"format": "int64",
"x-go-name": "TeamID",
"name": "teamId",
"in": "path",
"required": true
},
{
"x-go-name": "Body",
"name": "body",
@@ -6465,14 +6476,6 @@
"schema": {
"$ref": "#/definitions/TeamGroupMapping"
}
},
{
"type": "integer",
"format": "int64",
"x-go-name": "TeamID",
"name": "teamId",
"in": "path",
"required": true
}
],
"responses": {
@@ -6506,16 +6509,16 @@
{
"type": "integer",
"format": "int64",
"x-go-name": "GroupID",
"name": "groupId",
"x-go-name": "TeamID",
"name": "teamId",
"in": "path",
"required": true
},
{
"type": "integer",
"format": "int64",
"x-go-name": "TeamID",
"name": "teamId",
"x-go-name": "GroupID",
"name": "groupId",
"in": "path",
"required": true
}
@@ -8374,6 +8377,36 @@
},
"x-go-package": "github.com/grafana/grafana/pkg/api/dtos"
},
"AnnotationActions": {
"type": "object",
"properties": {
"canAdd": {
"type": "boolean",
"x-go-name": "CanAdd"
},
"canDelete": {
"type": "boolean",
"x-go-name": "CanDelete"
},
"canEdit": {
"type": "boolean",
"x-go-name": "CanEdit"
}
},
"x-go-package": "github.com/grafana/grafana/pkg/api/dtos"
},
"AnnotationPermission": {
"type": "object",
"properties": {
"dashboard": {
"$ref": "#/definitions/AnnotationActions"
},
"organization": {
"$ref": "#/definitions/AnnotationActions"
}
},
"x-go-package": "github.com/grafana/grafana/pkg/api/dtos"
},
"ApiKeyDTO": {
"type": "object",
"properties": {
@@ -8421,7 +8454,7 @@
"x-go-name": "ReportLogo"
}
},
"x-go-package": "github.com/grafana/grafana/pkg/extensions/report"
"x-go-package": "github.com/grafana/grafana/pkg/extensions/report/api"
},
"CalculateDiffTarget": {
"type": "object",
@@ -8537,7 +8570,7 @@
"x-go-name": "UserID"
}
},
"x-go-package": "github.com/grafana/grafana/pkg/extensions/report"
"x-go-package": "github.com/grafana/grafana/pkg/extensions/report/api"
},
"CreateAlertNotificationCommand": {
"type": "object",
@@ -8723,7 +8756,7 @@
"x-go-name": "TemplateVars"
}
},
"x-go-package": "github.com/grafana/grafana/pkg/extensions/report"
"x-go-package": "github.com/grafana/grafana/pkg/extensions/report/api"
},
"CreateOrgCommand": {
"type": "object",
@@ -8983,6 +9016,9 @@
"DashboardMeta": {
"type": "object",
"properties": {
"annotationsPermissions": {
"$ref": "#/definitions/AnnotationPermission"
},
"canAdmin": {
"type": "boolean",
"x-go-name": "CanAdmin"
@@ -9625,32 +9661,6 @@
},
"x-go-package": "github.com/grafana/grafana/pkg/tsdb/legacydata"
},
"DeleteAnnotationsCmd": {
"type": "object",
"properties": {
"alertId": {
"type": "integer",
"format": "int64",
"x-go-name": "AlertId"
},
"annotationId": {
"type": "integer",
"format": "int64",
"x-go-name": "AnnotationId"
},
"dashboardId": {
"type": "integer",
"format": "int64",
"x-go-name": "DashboardId"
},
"panelId": {
"type": "integer",
"format": "int64",
"x-go-name": "PanelId"
}
},
"x-go-package": "github.com/grafana/grafana/pkg/api/dtos"
},
"DeleteTokenCommand": {
"type": "object",
"properties": {
@@ -9952,18 +9962,18 @@
"x-go-name": "URL"
}
},
"x-go-package": "github.com/grafana/grafana/pkg/services/search"
"x-go-package": "github.com/grafana/grafana/pkg/models"
},
"HitList": {
"type": "array",
"items": {
"$ref": "#/definitions/Hit"
},
"x-go-package": "github.com/grafana/grafana/pkg/services/search"
"x-go-package": "github.com/grafana/grafana/pkg/models"
},
"HitType": {
"type": "string",
"x-go-package": "github.com/grafana/grafana/pkg/services/search"
"x-go-package": "github.com/grafana/grafana/pkg/models"
},
"ImportDashboardInput": {
"type": "object",
@@ -10395,6 +10405,27 @@
},
"x-go-package": "github.com/grafana/grafana/pkg/services/libraryelements"
},
"MassDeleteAnnotationsCmd": {
"type": "object",
"properties": {
"annotationId": {
"type": "integer",
"format": "int64",
"x-go-name": "AnnotationId"
},
"dashboardId": {
"type": "integer",
"format": "int64",
"x-go-name": "DashboardId"
},
"panelId": {
"type": "integer",
"format": "int64",
"x-go-name": "PanelId"
}
},
"x-go-package": "github.com/grafana/grafana/pkg/api/dtos"
},
"Metadata": {
"description": "Metadata contains user accesses for a given resource\nEx: map[string]bool{\"create\":true, \"delete\": true}",
"type": "object",
@@ -10984,7 +11015,7 @@
"x-go-name": "UseEmailsFromReport"
}
},
"x-go-package": "github.com/grafana/grafana/pkg/extensions/report"
"x-go-package": "github.com/grafana/grafana/pkg/extensions/report/api"
},
"ReportOptionsDTO": {
"type": "object",
@@ -11001,7 +11032,7 @@
"$ref": "#/definitions/TimeRangeDTO"
}
},
"x-go-package": "github.com/grafana/grafana/pkg/extensions/report"
"x-go-package": "github.com/grafana/grafana/pkg/extensions/report/api"
},
"Responses": {
"description": "The QueryData method the QueryDataHandler method will set the RefId\nproperty on the DataRespones' frames based on these RefIDs.",
@@ -11175,7 +11206,7 @@
"x-go-name": "WorkdaysOnly"
}
},
"x-go-package": "github.com/grafana/grafana/pkg/extensions/report"
"x-go-package": "github.com/grafana/grafana/pkg/extensions/report/api"
},
"SearchTeamQueryResult": {
"type": "object",
@@ -11286,7 +11317,7 @@
"x-go-name": "UserID"
}
},
"x-go-package": "github.com/grafana/grafana/pkg/extensions/report"
"x-go-package": "github.com/grafana/grafana/pkg/extensions/report/api"
},
"Status": {
"type": "object",
@@ -11562,7 +11593,7 @@
"x-go-name": "To"
}
},
"x-go-package": "github.com/grafana/grafana/pkg/extensions/report"
"x-go-package": "github.com/grafana/grafana/pkg/extensions/report/api"
},
"Token": {
"type": "object",
@@ -11663,6 +11694,15 @@
"format": "int64",
"x-go-name": "TokenExpiresWarnDays"
},
"trial": {
"type": "boolean",
"x-go-name": "Trial"
},
"trial_exp": {
"type": "integer",
"format": "int64",
"x-go-name": "TrialExpires"
},
"update_days": {
"type": "integer",
"format": "int64",
@@ -31,6 +31,8 @@ import { VariableWithMultiSupport } from 'app/features/variables/types';
import { store } from 'app/store/store';
import { AppNotificationTimeout } from 'app/types';
import config from '../../../core/config';
import { SQLCompletionItemProvider } from './cloudwatch-sql/completion/CompletionItemProvider';
import { ThrottlingErrorMessage } from './components/ThrottlingErrorMessage';
import { CloudWatchLanguageProvider } from './language_provider';
@@ -623,6 +625,10 @@ export class CloudWatchDatasource
return this.awsRequest(DS_QUERY_ENDPOINT, requestParams, headers).pipe(
map((response) => resultsToDataFrames({ data: response })),
catchError((err: FetchError) => {
if (config.featureToggles.datasourceQueryMultiStatus && err.status === 207) {
throw err;
}
if (err.status === 400) {
throw err;
}