API: Extract OpenAPI specification from source code using go-swagger (#40528)

* API: Using go-swagger for extracting OpenAPI specification from source code

* Merge Grafana Alerting spec

* Include enterprise endpoints (if enabled)

* Serve SwaggerUI under feature flag

* Fix building dev docker images

* Configure swaggerUI

* Add missing json tags

Co-authored-by: Ying WANG <ying.wang@grafana.com>
Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com>
This commit is contained in:
Sofia Papagiannaki 2022-02-08 14:38:43 +02:00 committed by GitHub
parent 9c2363ef08
commit 35fe58de37
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
61 changed files with 35314 additions and 74 deletions

View File

@ -11,7 +11,7 @@ COPY plugins-bundled plugins-bundled
RUN yarn install
COPY tsconfig.json .eslintrc .editorconfig .browserslistrc .prettierrc.js babel.config.json ./
COPY tsconfig.json .eslintrc .editorconfig .browserslistrc .prettierrc.js babel.config.json .linguirc ./
COPY public public
COPY tools tools
COPY scripts scripts
@ -30,6 +30,7 @@ COPY go.mod go.sum embed.go Makefile build.go package.json ./
COPY cue cue
COPY packages/grafana-schema packages/grafana-schema
COPY public/app/plugins public/app/plugins
COPY public/api-spec.json public/api-spec.json
COPY pkg pkg
COPY scripts scripts
COPY cue.mod cue.mod

View File

@ -12,7 +12,7 @@ COPY plugins-bundled plugins-bundled
RUN yarn install
COPY tsconfig.json .eslintrc .editorconfig .browserslistrc .prettierrc.js babel.config.json ./
COPY tsconfig.json .eslintrc .editorconfig .browserslistrc .prettierrc.js babel.config.json .linguirc ./
COPY public public
COPY tools tools
COPY scripts scripts
@ -33,6 +33,7 @@ COPY cue cue/
COPY cue.mod cue.mod/
COPY packages/grafana-schema packages/grafana-schema/
COPY public/app/plugins public/app/plugins/
COPY public/api-spec.json public/api-spec.json
RUN go mod verify
RUN make build-go

View File

@ -7,11 +7,13 @@ WIRE_TAGS = "oss"
-include local/Makefile
include .bingo/Variables.mk
.PHONY: all deps-go deps-js deps build-go build-server build-cli build-js build build-docker-full lint-go golangci-lint test-go test-js gen-ts test run run-frontend clean devenv devenv-down protobuf drone help
.PHONY: all deps-go deps-js deps build-go build-server build-cli build-js build build-docker-full build-docker-full-ubuntu lint-go golangci-lint test-go test-js gen-ts test run run-frontend clean devenv devenv-down protobuf drone help
GO = go
GO_FILES ?= ./pkg/...
SH_FILES ?= $(shell find ./scripts -name *.sh)
API_DEFINITION_FILES = $(shell find ./pkg/api/docs/definitions -name '*.go' -print)
SWAGGER_TAG ?= latest
all: deps build
@ -28,13 +30,62 @@ node_modules: package.json yarn.lock ## Install node modules.
@echo "install frontend dependencies"
YARN_ENABLE_PROGRESS_BARS=false yarn install --immutable
##@ Swagger
SPEC_TARGET = public/api-spec.json
MERGED_SPEC_TARGET := public/api-merged.json
NGALERT_SPEC_TARGET = pkg/services/ngalert/api/tooling/post.json
$(SPEC_TARGET): $(API_DEFINITION_FILES) ## Generate API spec
docker run --rm -it \
-e GOPATH=${HOME}/go:/go \
-e SWAGGER_GENERATE_EXTENSION=false \
-v ${HOME}/go:/go \
-v $$(pwd):/grafana \
-w $$(pwd)/pkg/api/docs quay.io/goswagger/swagger:$(SWAGGER_TAG) \
generate spec -m -o /grafana/public/api-spec.json \
-w /grafana/pkg/server \
-x "grafana/grafana/pkg/services/ngalert/api/tooling/definitions" \
-x "github.com/prometheus/alertmanager" \
-i /grafana/pkg/api/docs/tags.json
swagger-api-spec: $(SPEC_TARGET) $(MERGED_SPEC_TARGET)
$(NGALERT_SPEC_TARGET):
+$(MAKE) -C pkg/services/ngalert/api/tooling post.json
$(MERGED_SPEC_TARGET): $(SPEC_TARGET) $(NGALERT_SPEC_TARGET) ## Merge generated and ngalert API specs
go run pkg/api/docs/merge/merge_specs.go -o=public/api-merged.json $(<) pkg/services/ngalert/api/tooling/post.json
ensure_go-swagger_mac:
@hash swagger &>/dev/null || (brew tap go-swagger/go-swagger && brew install go-swagger)
--swagger-api-spec-mac: ensure_go-swagger_mac $(API_DEFINITION_FILES) ## Generate API spec (for M1 Mac)
swagger generate spec -m -w pkg/server -o public/api-spec.json \
-x "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions" \
-x "github.com/prometheus/alertmanager" \
-i pkg/api/docs/tags.json
swagger-api-spec-mac: --swagger-api-spec-mac $(MERGED_SPEC_TARGET)
validate-api-spec: $(MERGED_SPEC_TARGET) ## Validate API spec
docker run --rm -it \
-e GOPATH=${HOME}/go:/go \
-e SWAGGER_GENERATE_EXTENSION=false \
-v ${HOME}/go:/go \
-v $$(pwd):/grafana \
-w $$(pwd)/pkg/api/docs quay.io/goswagger/swagger:$(SWAGGER_TAG) \
validate /grafana/$(<)
clean-api-spec:
rm $(SPEC_TARGET) $(MERGED_SPEC_TARGET)
##@ Building
gen-go: $(WIRE)
@echo "generate go files"
$(WIRE) gen -tags $(WIRE_TAGS) ./pkg/server ./pkg/cmd/grafana-cli/runner
build-go: gen-go ## Build all Go binaries.
build-go: $(MERGED_SPEC_TARGET) gen-go ## Build all Go binaries.
@echo "build go files"
$(GO) run build.go build
@ -99,6 +150,11 @@ build-docker-full: ## Build Docker image for development.
@echo "build docker container"
docker build --tag grafana/grafana:dev .
build-docker-full-ubuntu: ## Build Docker image based on Ubuntu for development.
@echo "build docker container"
docker build --tag grafana/grafana:dev-ubuntu -f ./Dockerfile.ubuntu .
##@ Services
# create docker-compose file with provided sources and start them

4
go.mod
View File

@ -167,10 +167,10 @@ require (
github.com/go-openapi/analysis v0.20.1 // indirect
github.com/go-openapi/errors v0.20.0 // indirect
github.com/go-openapi/jsonpointer v0.19.5 // indirect
github.com/go-openapi/jsonreference v0.19.5 // indirect
github.com/go-openapi/jsonreference v0.19.6 // indirect
github.com/go-openapi/loads v0.20.2 // indirect
github.com/go-openapi/runtime v0.19.29 // indirect
github.com/go-openapi/spec v0.20.3 // indirect
github.com/go-openapi/spec v0.20.4 // indirect
github.com/go-openapi/swag v0.19.15 // indirect
github.com/go-openapi/validate v0.20.2 // indirect
github.com/gogo/googleapis v1.4.1 // indirect

4
go.sum
View File

@ -867,6 +867,8 @@ github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL9
github.com/go-openapi/jsonreference v0.19.4/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg=
github.com/go-openapi/jsonreference v0.19.5 h1:1WJP/wi4OjB4iV8KVbH73rQaoialJrqv8gitZLxGLtM=
github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg=
github.com/go-openapi/jsonreference v0.19.6 h1:UBIxjkht+AWIgYzCDSv2GN+E/togfwXUJFRTWhl2Jjs=
github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns=
github.com/go-openapi/loads v0.17.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=
github.com/go-openapi/loads v0.17.2/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=
github.com/go-openapi/loads v0.18.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=
@ -907,6 +909,8 @@ github.com/go-openapi/spec v0.20.0/go.mod h1:+81FIL1JwC5P3/Iuuozq3pPE9dXdIEGxFut
github.com/go-openapi/spec v0.20.1/go.mod h1:93x7oh+d+FQsmsieroS4cmR3u0p/ywH649a3qwC9OsQ=
github.com/go-openapi/spec v0.20.3 h1:uH9RQ6vdyPSs2pSy9fL8QPspDF2AMIMPtmK5coSSjtQ=
github.com/go-openapi/spec v0.20.3/go.mod h1:gG4F8wdEDN+YPBMVnzE85Rbhf+Th2DTvA9nFPQ5AYEg=
github.com/go-openapi/spec v0.20.4 h1:O8hJrt0UMnhHcluhIdUgCLRWyM2x7QkBXRvOs7m+O1M=
github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I=
github.com/go-openapi/strfmt v0.17.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU=
github.com/go-openapi/strfmt v0.17.2/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU=
github.com/go-openapi/strfmt v0.18.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU=

View File

@ -37,5 +37,6 @@ export interface FeatureToggles {
showFeatureFlagsInUI?: boolean;
disable_http_request_histogram?: boolean;
validatedQueries?: boolean;
swaggerUi?: boolean;
featureHighlights?: boolean;
}

View File

@ -140,6 +140,10 @@ func (hs *HTTPServer) registerRoutes() {
// expose plugin file system assets
r.Get("/public/plugins/:pluginId/*", hs.getPluginAssets)
if hs.Features.IsEnabled(featuremgmt.FlagSwaggerUi) {
r.Get("/swagger-ui", swaggerUI)
}
// authed api
r.Group("/api", func(apiRoute routing.RouteRegister) {
// user (signed in)

View File

@ -0,0 +1,67 @@
package definitions
import (
"github.com/grafana/grafana/pkg/api/dtos"
)
// swagger:route GET /admin/settings admin getSettings
//
// Fetch settings.
//
// If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `settings:read` and scopes: `settings:*`, `settings:auth.saml:` and `settings:auth.saml:enabled` (property level).
//
// Security:
// - basic:
//
// Responses:
// 200: getSettingsResponse
// 401: unauthorisedError
// 403: forbiddenError
// swagger:route GET /admin/stats admin getStats
//
// Fetch Grafana Stats.
//
// Only works with Basic Authentication (username and password). See introduction for an explanation.
// If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `server:stats:read`.
//
// Responses:
// 200: getStatsResponse
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route POST /admin/pause-all-alerts admin pauseAllAlerts
//
// Pause/unpause all (legacy) alerts.
//
// Security:
// - basic:
//
// Responses:
// 200: pauseAlertsResponse
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:parameters pauseAllAlerts
type PauseAllAlertsParam struct {
// in:body
// required:true
Body dtos.PauseAllAlertsCommand `json:"body"`
}
// swagger:response pauseAlertsResponse
type PauseAllAlertsResponse struct {
// in:body
Body struct {
// AlertsAffected is the number of the affected alerts.
// required: true
AlertsAffected int64 `json:"alertsAffected"`
// required: true
Message string `json:"message"`
// Alert result state
// required true
State string `json:"state"`
} `json:"body"`
}

View File

@ -0,0 +1,68 @@
package definitions
// swagger:route POST /admin/ldap/reload admin_ldap reloadLDAP
//
// Reloads the LDAP configuration.
//
// If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `ldap.config:reload`.
//
// Security:
// - basic:
//
// Responses:
// 200: okResponse
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route POST /admin/ldap/sync/{user_id} admin_ldap syncLDAPUser
//
// Enables a single Grafana user to be synchronized against LDAP.
//
// If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `ldap.user:sync`.
//
// Security:
// - basic:
//
// Responses:
// 200: okResponse
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route GET /admin/ldap/{user_name} admin_ldap getLDAPUser
//
// Finds an user based on a username in LDAP. This helps illustrate how would the particular user be mapped in Grafana when synced.
//
// If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `ldap.user:read`.
//
// Security:
// - basic:
//
// Responses:
// 200: okResponse
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route GET /admin/ldap/status admin_ldap getLDAPStatus
//
// Attempts to connect to all the configured LDAP servers and returns information on whenever they're available or not.
//
// If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `ldap.status:read`.
//
// Security:
// - basic:
//
// Responses:
// 200: okResponse
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:parameters getLDAPUser
type UserNameParam struct {
// in:path
// required:true
UserID string `json:"user_name"`
}

View File

@ -0,0 +1,81 @@
package definitions
// swagger:route POST /admin/provisioning/dashboards/reload admin_provisioning reloadProvisionedDashboards
//
// Reload dashboard provisioning configurations.
//
// Reloads the provisioning config files for dashboards again. It wont return until the new provisioned entities are already stored in the database. In case of dashboards, it will stop polling for changes in dashboard files and then restart it with new configurations after returning.
// If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `provisioning:reload` and scope `provisioners:dashboards`.
//
// Security:
// - basic:
//
// Responses:
// 200: okResponse
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route POST /admin/provisioning/datasources/reload admin_provisioning reloadProvisionedDatasources
//
// Reload datasource provisioning configurations.
//
// Reloads the provisioning config files for datasources again. It wont return until the new provisioned entities are already stored in the database. In case of dashboards, it will stop polling for changes in dashboard files and then restart it with new configurations after returning.
// If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `provisioning:reload` and scope `provisioners:datasources`.
//
// Security:
// - basic:
//
// Responses:
// 200: okResponse
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route POST /admin/provisioning/plugins/reload admin_provisioning reloadProvisionedPlugins
//
// Reload plugin provisioning configurations.
//
// Reloads the provisioning config files for plugins again. It wont return until the new provisioned entities are already stored in the database. In case of dashboards, it will stop polling for changes in dashboard files and then restart it with new configurations after returning.
// If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `provisioning:reload` and scope `provisioners:plugin`.
//
// Security:
// - basic:
//
// Responses:
// 200: okResponse
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route POST /admin/provisioning/notifications/reload admin_provisioning reloadProvisionedAlertNotifiers
//
// Reload legacy alert notifier provisioning configurations.
//
// Reloads the provisioning config files for legacy alert notifiers again. It wont return until the new provisioned entities are already stored in the database. In case of dashboards, it will stop polling for changes in dashboard files and then restart it with new configurations after returning.
// If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `provisioning:reload` and scope `provisioners:notifications`.
//
// Security:
// - basic:
//
// Responses:
// 200: okResponse
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route POST /admin/provisioning/accesscontrol/reload admin_provisioning reloadProvisionedAccessControl
//
// Reload access control provisioning configurations.
//
// Reloads the provisioning config files for access control again. It wont return until the new provisioned entities are already stored in the database. In case of dashboards, it will stop polling for changes in dashboard files and then restart it with new configurations after returning.
// If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `provisioning:reload` and scope `provisioners:accesscontrol`.
//
// Security:
// - basic:
//
// Responses:
// 200: okResponse
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError

View File

@ -0,0 +1,255 @@
package definitions
import (
"github.com/grafana/grafana/pkg/api/dtos"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/setting"
)
// swagger:route POST /admin/users admin_users createUser
//
// Create new user.
//
// If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users:create`.
// Note that OrgId is an optional parameter that can be used to assign a new user to a different organization when `auto_assign_org` is set to `true`.
//
// Security:
// - basic:
//
// Responses:
// 200: createUserResponse
// 400: badRequestError
// 401: unauthorisedError
// 403: forbiddenError
// 412: preconditionFailedError
// 500: internalServerError
// swagger:route PUT /admin/users/{user_id}/password admin_users setPassword
//
// Set password for user.
//
// 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:*`.
//
// Security:
// - basic:
//
// Responses:
// 200: okResponse
// 400: badRequestError
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route PUT /admin/users/{user_id}/permissions admin_users setPermissions
//
// Set permissions for user.
//
// Only works with Basic Authentication (username and password). See introduction for an explanation.
// If 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:*`.
//
// Responses:
// 200: okResponse
// 400: badRequestError
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route DELETE /admin/users/{user_id} admin_users deleteUser
//
// Delete global User.
//
// 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:*`.
//
// Security:
// - basic:
//
// Responses:
// 200: okResponse
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:route POST /admin/users/{user_id}/disable admin_users disableUser
//
// Disable user.
//
// 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).
//
// Security:
// - basic:
//
// Responses:
// 200: okResponse
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:route POST /admin/users/{user_id}/enable admin_users enableUser
//
// Enable user.
//
// 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).
//
// Security:
// - basic:
//
// Responses:
// 200: okResponse
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:route GET /admin/users/{user_id}/quotas admin_users getUserQuota
//
// Fetch user quota.
//
// 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).
//
// Security:
// - basic:
//
// Responses:
// 200: getQuotaResponse
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:route PUT /admin/users/{user_id}/quotas/{quota_target} admin_users updateUserQuota
//
// Update user quota.
//
// 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).
//
// Security:
// - basic:
//
// Responses:
// 200: okResponse
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:route GET /admin/users/{user_id}/auth-tokens admin_users getAuthTokens
//
// Return a list of all auth tokens (devices) that the user currently have logged in from.
// 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:*`.
//
// Security:
// - basic:
//
// Responses:
// 200: getAuthTokensResponse
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route POST /admin/users/{user_id}/revoke-auth-token admin_users revokeAuthToken
//
// Revoke auth token for user.
//
// 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.
// If 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:*`.
//
// Security:
// - basic:
//
// Responses:
// 200: okResponse
// 400: badRequestError
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:route POST /admin/users/{user_id}/logout admin_users logoutUser
//
// 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.
// 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:*`.
//
// Security:
// - basic:
//
// Responses:
// 200: okResponse
// 400: badRequestError
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:parameters setPassword
type SetPasswordParam struct {
// in:body
// required:true
Body dtos.AdminUpdateUserPasswordForm `json:"body"`
}
// swagger:parameters revokeAuthToken revokeSignedINAuthTokenCmd
type RevokeAuthTokenParam struct {
// in:body
// required:true
Body models.RevokeAuthTokenCmd `json:"body"`
}
// swagger:parameters createUser
type CreateUserParam struct {
// in:body
// required:true
Body dtos.AdminCreateUserForm `json:"body"`
}
// swagger:parameters updateUserQuota updateOrgQuota
type TargeQuotaParam struct {
// in:path
// required:true
QuotaTarget string `json:"quota_target"`
}
// swagger:parameters updateUserQuota
type UpdateUserQuotaParam struct {
// in:body
// required:true
Body models.UpdateUserQuotaCmd `json:"body"`
}
// swagger:parameters setPermissions
type SetPermissionsParam struct {
// in:body
// required:true
Body dtos.AdminUpdateUserPermissionsForm `json:"body"`
}
// swagger:response createUserResponse
type CreateUserResponse struct {
// in:body
Body models.UserIdDTO `json:"body"`
}
// swagger:response getSettingsResponse
type GetSettingsResponse struct {
// in:body
Body setting.SettingsBag `json:"body"`
}
// swagger:response getStatsResponse
type GetStatsResponse struct {
// in:body
Body models.AdminStats `json:"body"`
}
// swagger:response getAuthTokensResponse
type GetAuthTokensResponse struct {
// in:body
Body []*models.UserToken `json:"body"`
}
// swagger:response getQuotaResponse
type GetQuotaResponseResponse struct {
// in:body
Body []*models.UserQuotaDTO `json:"body"`
}

View File

@ -0,0 +1,240 @@
package definitions
import (
"github.com/grafana/grafana/pkg/api/dtos"
"github.com/grafana/grafana/pkg/services/annotations"
)
// swagger:route GET /annotations annotations getAnnotations
//
// Find Annotations.
//
// Starting in Grafana v6.4 regions annotations are now returned in one entity that now includes the timeEnd property.
//
// Responses:
// 200: getAnnotationsResponse
// 401: unauthorisedError
// 500: internalServerError
// swagger:route POST /annotations/mass-delete annotations massDeleteAnnotations
//
// Delete multiple annotations.
//
// Responses:
// 200: okResponse
// 401: unauthorisedError
// 500: internalServerError
// swagger:route POST /annotations annotations createAnnotation
//
// Create Annotation.
//
// Creates an annotation in the Grafana database. The dashboardId and panelId fields are optional. If they are not specified then a global annotation is created and can be queried in any dashboard that adds the Grafana annotations data source. When creating a region annotation include the timeEnd property.
// The format for `time` and `timeEnd` should be epoch numbers in millisecond resolution.
// The response for this HTTP request is slightly different in versions prior to v6.4. In prior versions you would also get an endId if you where creating a region. But in 6.4 regions are represented using a single event with time and timeEnd properties.
//
// Responses:
// 200: createAnnotationResponse
// 400: badRequestError
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route POST /annotations/graphite annotations createGraphiteAnnotation
//
// Create Annotation in Graphite format.
//
// Creates an annotation by using Graphite-compatible event format. The `when` and `data` fields are optional. If `when` is not specified then the current time will be used as annotations timestamp. The `tags` field can also be in prior to Graphite `0.10.0` format (string with multiple tags being separated by a space).
//
// Responses:
// 200: createAnnotationResponse
// 400: badRequestError
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route PUT /annotations/{annotation_id} annotations updateAnnotation
//
// Update Annotation.
//
// Updates all properties of an annotation that matches the specified id. To only update certain property, consider using the Patch Annotation operation.
//
// Responses:
// 200: okResponse
// 400: badRequestError
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route PATCH /annotations/{annotation_id} annotations patchAnnotation
//
// Patch Annotation
//
// Updates one or more properties of an annotation that matches the specified ID.
// This operation currently supports updating of the `text`, `tags`, `time` and `timeEnd` properties.
// This is available in Grafana 6.0.0-beta2 and above.
//
// Responses:
// 200: okResponse
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:route DELETE /annotations/{annotation_id} annotations deleteAnnotation
//
// Delete Annotation By ID.
//
// Deletes the annotation that matches the specified ID.
//
// Responses:
// 200: okResponse
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route GET /annotations/tags annotations getAnnotationTags
//
// Find Annotations Tags.
//
// Find all the event tags created in the annotations.
//
// Responses:
// 200: getAnnotationTagsResponse
// 401: unauthorisedError
// 500: internalServerError
// swagger:parameters updateAnnotation patchAnnotation deleteAnnotation
type AnnotationIDParam struct {
// in:path
// required:true
AnnotationID string `json:"annotation_id"`
}
// swagger:parameters getAnnotations
type GetAnnotationsParams struct {
// Find annotations created after specific epoch datetime in milliseconds.
// in:query
// required:false
From int64 `json:"from"`
// Find annotations created before specific epoch datetime in milliseconds.
// in:query
// required:false
To int64 `json:"to"`
// Limit response to annotations created by specific user.
// in:query
// required:false
UserID int64 `json:"userId"`
// Find annotations for a specified alert.
// in:query
// required:false
AlertID int64 `json:"alertId"`
// Find annotations that are scoped to a specific dashboard
// in:query
// required:false
DashboardID int64 `json:"dashboardId"`
// Find annotations that are scoped to a specific panel
// in:query
// required:false
PanelID int64 `json:"panelId"`
// Max limit for results returned.
// in:query
// required:false
Limit int64 `json:"limit"`
// Use this to filter global annotations. Global annotations are annotations from an annotation data source that are not connected specifically to a dashboard or panel. You can filter by multiple tags.
// in:query
// required:false
// type: array
// collectionFormat: multi
Tags []string `json:"tags"`
// Return alerts or user created annotations
// in:query
// required:false
// Description:
// * `alert`
// * `annotation`
// enum: alert,annotation
Type string `json:"type"`
// Match any or all tags
// in:query
// required:false
MatchAny bool `json:"matchAny"`
}
// swagger:parameters getAnnotationTags
type GetAnnotationTagssParams struct {
// Tag is a string that you can use to filter tags.
// in:query
// required:false
Tag string `json:"tag"`
// Max limit for results returned.
// in:query
// required:false
// default: 100
Limit string `json:"limit"`
}
// swagger:parameters massDeleteAnnotations
type MassDeleteAnnotationsParams struct {
// in:body
// required:true
Body dtos.DeleteAnnotationsCmd `json:"body"`
}
// swagger:parameters createAnnotation
type CreateAnnotationParams struct {
// in:body
// required:true
Body dtos.PostAnnotationsCmd `json:"body"`
}
// swagger:parameters createGraphiteAnnotation
type CreateGraphiteAnnotationParams struct {
// in:body
// required:true
Body dtos.PostGraphiteAnnotationsCmd `json:"body"`
}
// swagger:parameters updateAnnotation
type UpdateAnnotationParams struct {
// in:body
// required:true
Body dtos.UpdateAnnotationsCmd `json:"body"`
}
// swagger:parameters patchAnnotation
type PatchAnnotationParams struct {
// in:body
// required:true
Body dtos.PatchAnnotationsCmd `json:"body"`
}
// swagger:response getAnnotationsResponse
type GetAnnotationsResponse struct {
// The response message
// in: body
Body []*annotations.ItemDTO `json:"body"`
}
// swagger:response createAnnotationResponse
type CreateAnnotationResponse struct {
// The response message
// in: body
Body struct {
// ID Identifier of the created annotation.
// required: true
// example: 65
ID int64 `json:"id"`
// Message Message of the created annotation.
// required: true
Message string `json:"message"`
} `json:"body"`
}
// swagger:response getAnnotationTagsResponse
type GetAnnotationTagsResponse struct {
// The response message
// in: body
Body annotations.GetAnnotationTagsResponse `json:"body"`
}

View File

@ -0,0 +1,81 @@
package definitions
import (
"github.com/grafana/grafana/pkg/api/dtos"
"github.com/grafana/grafana/pkg/models"
)
// swagger:route GET /auth/keys api_keys getAPIkeys
//
// Get auth keys.
//
// Will return auth keys.
//
// Responses:
// 200: getAPIkeyResponse
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:route POST /auth/keys api_keys addAPIkey
//
// Creates an API key.
//
// Will return details of the created API key
//
// Responses:
// 200: postAPIkeyResponse
// 400: badRequestError
// 401: unauthorisedError
// 403: forbiddenError
// 409: conflictError
// 500: internalServerError
// swagger:route DELETE /auth/keys/{id} api_keys deleteAPIkey
//
// Delete API key.
//
// Responses:
// 200: okResponse
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:parameters getAPIkeys
type GetAPIkeysParams struct {
// Show expired keys
// in:query
// required:false
// default:false
IncludeExpired bool `json:"includeExpired"`
}
// swagger:parameters addAPIkey
type AddAPIkeyParams struct {
// in:body
// required:true
Body models.AddApiKeyCommand
}
// swagger:parameters deleteAPIkey
type DeleteAPIkeyParams struct {
// in:path
// required:true
ID int64 `json:"id"`
}
// swagger:response getAPIkeyResponse
type GetAPIkeyResponse struct {
// The response message
// in: body
Body []*models.ApiKeyDTO `json:"body"`
}
// swagger:response postAPIkeyResponse
type PostAPIkeyResponse struct {
// The response message
// in: body
Body dtos.NewApiKeyResult `json:"body"`
}

View File

@ -0,0 +1,257 @@
package definitions
import (
"github.com/grafana/grafana/pkg/api/dtos"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/dashboardimport"
)
// swagger:route GET /dashboards/uid/{uid} dashboards getDashboardByUID
//
// Get dashboard by uid.
//
// Will return the dashboard given the dashboard unique identifier (uid).
//
// Responses:
// 200: dashboardResponse
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// DeleteDashboardByUID swagger:route DELETE /dashboards/uid/{uid} dashboards deleteDashboardByUID
//
// Delete dashboard by uid.
//
// Will delete the dashboard given the specified unique identifier (uid).
//
// Responses:
// 200: deleteDashboardResponse
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:route POST /dashboards/calculate-diff dashboards calcDashboardDiff
//
// Perform diff on two dashboards.
//
// Produces:
// - application/json
// - text/html
//
// Responses:
// 200: dashboardDiffResponse
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route POST /dashboards/trim dashboards trimDashboard
//
// Trim defaults from dashboard.
//
// Responses:
// 200: trimDashboardResponse
// 401: unauthorisedError
// 500: internalServerError
// swagger:route POST /dashboards/db dashboards postDashboard
//
// Create / Update dashboard
//
// Creates a new dashboard or updates an existing dashboard.
//
// Responses:
// 200: postDashboardResponse
// 400: badRequestError
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 412: preconditionFailedError
// 422: unprocessableEntityError
// 500: internalServerError
// swagger:route GET /dashboards/home dashboards getHomeDashboard
//
// Get home dashboard.
//
// Responses:
// 200: getHomeDashboardResponse
// 401: unauthorisedError
// 500: internalServerError
// swagger:route GET /dashboards/tags dashboards getDashboardTags
//
// Get all dashboards tags of an organisation.
//
// Responses:
// 200: dashboardsTagsResponse
// 401: unauthorisedError
// 500: internalServerError
// swagger:route POST /dashboards/import dashboards importDashboard
//
// Import dashboard.
//
// Responses:
// 200: importDashboardResponse
// 400: badRequestError
// 401: unauthorisedError
// 412: preconditionFailedError
// 422: unprocessableEntityError
// 500: internalServerError
// swagger:parameters getDashboardByUID deleteDashboardByUID
type UID struct {
// in:path
// required:true
UID string `json:"uid"`
}
// swagger:parameters postDashboard
type PostDashboardParam struct {
// in:body
// required:true
Body models.SaveDashboardCommand
}
// swagger:parameters calcDashboardDiff
type CalcDashboardDiffOptions struct {
// in:body
// required:true
Body struct {
Base dtos.CalculateDiffTarget `json:"base" binding:"Required"`
New dtos.CalculateDiffTarget `json:"new" binding:"Required"`
// The type of diff to return
// Description:
// * `basic`
// * `json`
// Enum: basic,json
DiffType string `json:"diffType" binding:"Required"`
}
}
// swagger:parameters trimDashboard
type TrimDashboardParam struct {
// in:body
// required:true
Body models.TrimDashboardCommand
}
// swagger:parameters importDashboard
type ImportDashboardParam struct {
// in:body
// required:true
Body dashboardimport.ImportDashboardRequest
}
// swagger:response dashboardResponse
type DashboardResponse struct {
// The response message
// in: body
Body dtos.DashboardFullWithMeta `json:"body"`
}
// swagger:response deleteDashboardResponse
type DeleteDashboardResponse struct {
// The response message
// in: body
Body struct {
// ID Identifier of the deleted dashboard.
// required: true
// example: 65
ID int64 `json:"id"`
// Title Title of the deleted dashboard.
// required: true
// example: My Dashboard
Title string `json:"title"`
// Message Message of the deleted dashboard.
// required: true
// example: Dashboard My Dashboard deleted
Message string `json:"message"`
} `json:"body"`
}
// Create/update dashboard response.
// swagger:response postDashboardResponse
type PostDashboardResponse struct {
// in: body
Body struct {
// Status status of the response.
// required: true
// example: success
Status string `json:"status"`
// Slug The slug of the dashboard.
// required: true
// example: my-dashboard
Slug string `json:"title"`
// Version The version of the dashboard.
// required: true
// example: 2
Verion int64 `json:"version"`
// ID The unique identifier (id) of the created/updated dashboard.
// required: true
// example: 1
ID string `json:"id"`
// UID The unique identifier (uid) of the created/updated dashboard.
// required: true
// example: nHz3SXiiz
UID string `json:"uid"`
// URL The relative URL for accessing the created/updated dashboard.
// required: true
// example: /d/nHz3SXiiz/my-dashboard
URL string `json:"url"`
} `json:"body"`
}
// Calculate dashboard diff response.
// swagger:response dashboardDiffResponse
type DashboardDiffResponse struct {
// in: body
Body []byte `json:"body"`
}
// Trimmed dashboard response.
// swagger:response trimDashboardResponse
type TrimDashboardResponse struct {
// in: body
Body dtos.TrimDashboardFullWithMeta `json:"body"`
}
// Home dashboard response.
// swagger:response getHomeDashboardResponse
type GetHomeDashboardResponse struct {
// in: body
Body GetHomeDashboardResponseBody `json:"body"`
}
// swagger:response dashboardsTagsResponse
type DashboardsTagsResponse struct {
// in: body
Body []*models.DashboardTagCloudItem `json:"body"`
}
// swagger:response importDashboardResponse
type ImportDashboardResponse struct {
// in: body
Body dashboardimport.ImportDashboardResponse `json:"body"`
}
// Get home dashboard response.
// swagger:model GetHomeDashboardResponse
type GetHomeDashboardResponseBody struct {
// swagger:allOf
// required: false
dtos.DashboardFullWithMeta
// swagger:allOf
// required: false
dtos.DashboardRedirect
}

View File

@ -0,0 +1,44 @@
package definitions
import (
"github.com/grafana/grafana/pkg/api/dtos"
"github.com/grafana/grafana/pkg/models"
)
// swagger:route GET /dashboards/id/{DashboardID}/permissions dashboard_permissions getDashboardPermissions
//
// Gets all existing permissions for the given dashboard.
//
// Responses:
// 200: getDashboardPermissionsResponse
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:route POST /dashboards/id/{DashboardID}/permissions dashboard_permissions postDashboardPermissions
//
// Updates permissions for a dashboard.
//
// This operation will remove existing permissions if theyre not included in the request.
//
// Responses:
// 200: okResponse
// 400: badRequestError
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:parameters postDashboardPermissions updateFolderPermissions
type PostDashboardPermissionsParam struct {
// in:body
// required:true
Body dtos.UpdateDashboardAclCommand
}
// swagger:response getDashboardPermissionsResponse
type GetDashboardPermissionsResponse struct {
// in: body
Body []*models.DashboardAclInfoDTO `json:"body"`
}

View File

@ -0,0 +1,77 @@
package definitions
import "github.com/grafana/grafana/pkg/models"
// swagger:route GET /dashboards/id/{DashboardID}/versions dashboard_versions getDashboardVersions
//
// Gets all existing versions for the dashboard.
//
// Responses:
// 200: dashboardVersionsResponse
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:route GET /dashboards/id/{DashboardID}/versions/{DashboardVersionID} dashboard_versions getDashboardVersion
//
// Get a specific dashboard version.
//
// Responses:
// 200: dashboardVersionResponse
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:route POST /dashboards/id/{DashboardID}/restore dashboard_versions restoreDashboardVersion
//
// Restore a dashboard to a given dashboard version.
//
// Responses:
// 200: postDashboardResponse
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:parameters getDashboardVersions getDashboardVersion restoreDashboardVersion
// swagger:parameters getDashboardPermissions postDashboardPermissions
// swagger:parameters renderReportPDF
type DashboardIdParam struct {
// in:path
DashboardID int64
}
// swagger:parameters getDashboardVersion
type DashboardVersionIdParam struct {
// in:path
DashboardVersionID int64
}
// swagger:parameters getDashboardVersions
type GetDashboardVersionsParams struct {
// Maximum number of results to return
// in:query
// required:false
// default:0
Limit int `json:"limit"`
// Version to start from when returning queries
// in:query
// required:false
// default:0
Start int `json:"start"`
}
// swagger:response dashboardVersionsResponse
type DashboardVersionsResponse struct {
// in: body
Body []*models.DashboardVersionDTO `json:"body"`
}
// swagger:response dashboardVersionResponse
type DashboardVersionResponse struct {
// in: body
Body *models.DashboardVersionMeta `json:"body"`
}

View File

@ -0,0 +1,350 @@
package definitions
import (
"github.com/grafana/grafana/pkg/api/dtos"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/tsdb/legacydata"
)
// swagger:route GET /datasources datasources getDatasources
//
// Get all data sources.
//
// If you are running Grafana Enterprise and have Fine-grained access control enabled
// you need to have a permission with action: `datasources:read` and scope: `datasources:*`.
//
// Responses:
// 200: getDatasourcesResponse
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route POST /datasources datasources addDatasource
//
// Create a data source.
//
// By defining `password` and `basicAuthPassword` under secureJsonData property
// Grafana encrypts them securely as an encrypted blob in the database.
// The response then lists the encrypted fields under secureJsonFields.
//
// If you are running Grafana Enterprise and have Fine-grained access control enabled
// you need to have a permission with action: `datasources:create`
//
// Responses:
// 200: createOrUpdateDatasourceResponse
// 401: unauthorisedError
// 403: forbiddenError
// 409: conflictError
// 500: internalServerError
// swagger:route PUT /datasources/{datasource_id} datasources updateDatasource
//
// Update an existing data source.
//
// Similar to creating a data source, `password` and `basicAuthPassword` should be defined under
// secureJsonData in order to be stored securely as an encrypted blob in the database. Then, the
// encrypted fields are listed under secureJsonFields section in the response.
//
// If you are running Grafana Enterprise and have Fine-grained access control enabled
// you need to have a permission with action: `datasources:write` and scopes: `datasources:*`, `datasources:id:*` and `datasources:id:1` (single data source).
//
// Responses:
// 200: createOrUpdateDatasourceResponse
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route DELETE /datasources/{datasource_id} datasources deleteDatasourceByID
//
// Delete an existing data source by id.
//
// If you are running Grafana Enterprise and have Fine-grained access control enabled
// you need to have a permission with action: `datasources:delete` and scopes: `datasources:*`, `datasources:id:*` and `datasources:id:1` (single data source).
//
// Responses:
// 200: okResponse
// 401: unauthorisedError
// 404: notFoundError
// 403: forbiddenError
// 500: internalServerError
// swagger:route DELETE /datasources/uid/{datasource_uid} datasources deleteDatasourceByUID
//
// Delete an existing data source by UID.
//
// If you are running Grafana Enterprise and have Fine-grained access control enabled
// you need to have a permission with action: `datasources:delete` and scopes: `datasources:*`, `datasources:uid:*` and `datasources:uid:kLtEtcRGk` (single data source).
//
// Responses:
// 200: okResponse
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:route DELETE /datasources/name/{datasource_name} datasources deleteDatasourceByName
//
// Delete an existing data source by name.
//
// If you are running Grafana Enterprise and have Fine-grained access control enabled
// you need to have a permission with action: `datasources:delete` and scopes: `datasources:*`, `datasources:name:*` and `datasources:name:test_datasource` (single data source).
//
// Responses:
// 200: deleteDatasourceByNameResponse
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:route GET /datasources/{datasource_id} datasources getDatasourceByID
//
// Get a single data source by Id.
//
// If you are running Grafana Enterprise and have Fine-grained access control enabled
// you need to have a permission with action: `datasources:read` and scopes: `datasources:*`, `datasources:id:*` and `datasources:id:1` (single data source).
//
// Responses:
// 200: getDatasourceResponse
// 400: badRequestError
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:route GET /datasources/uid/{datasource_uid} datasources getDatasourceByUID
//
// Get a single data source by UID.
//
// If you are running Grafana Enterprise and have Fine-grained access control enabled
// you need to have a permission with action: `datasources:read` and scopes: `datasources:*`, `datasources:uid:*` and `datasources:uid:kLtEtcRGk` (single data source).
//
// Responses:
// 200: getDatasourceResponse
// 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.
//
// If you are running Grafana Enterprise and have Fine-grained access control enabled
// you need to have a permission with action: `datasources:read` and scopes: `datasources:*`, `datasources:name:*` and `datasources:name:test_datasource` (single data source).
//
// Responses:
// 200: getDatasourceResponse
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route GET /datasources/id/{datasource_name} datasources getDatasourceIdByName
//
// Get data source Id by Name.
//
// If you are running Grafana Enterprise and have Fine-grained access control enabled
// you need to have a permission with action: `datasources:read` and scopes: `datasources:*`, `datasources:name:*` and `datasources:name:test_datasource` (single data source).
//
// Responses:
// 200: getDatasourceIDresponse
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:route GET /datasources/proxy/{datasource_id}/{datasource_proxy_route} datasources datasourceProxyGETcalls
//
// Data source proxy GET calls.
//
// Proxies all calls to the actual data source.
//
// Responses:
// 200:
// 400: badRequestError
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:route POST /datasources/proxy/{datasource_id}/{datasource_proxy_route} datasources datasourceProxyPOSTcalls
//
// Data source proxy POST calls.
//
// Proxies all calls to the actual data source. The data source should support POST methods for the specific path and role as defined
//
// Responses:
// 201:
// 202:
// 400: badRequestError
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:route DELETE /datasources/proxy/{datasource_id}/{datasource_proxy_route} datasources datasourceProxyDELETEcalls
//
// Data source proxy DELETE calls.
//
// Proxies all calls to the actual data source.
//
// Responses:
// 202:
// 400: badRequestError
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:route POST /tsdb/query datasources queryDatasource
//
// Query metrics.
//
// Queries a data source having backend implementation.
//
// Most of Grafanas builtin data sources have backend implementation.
//
// If you are running Grafana Enterprise and have Fine-grained access control enabled
// you need to have a permission with action: `datasources:query`.
//
// Responses:
// 200: queryDatasourceResponse
// 401: unauthorisedError
// 400: badRequestError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:parameters updateDatasource deleteDatasourceByID getDatasourceByID datasourceProxyGETcalls datasourceProxyPOSTcalls datasourceProxyDELETEcalls
// swagger:parameters enablePermissions disablePermissions getPermissions deletePermissions
type DatasourceID struct {
// in:path
// required:true
DatasourceID string `json:"datasource_id"`
}
// swagger:parameters deleteDatasourceByUID getDatasourceByUID
type DatasourceUID struct {
// in:path
// required:true
DatasourceUID string `json:"datasource_uid"`
}
// swagger:parameters getDatasourceByName deleteDatasourceByName getDatasourceIdByName
type DatasourceName struct {
// in:path
// required:true
DatasourceName string `json:"datasource_name"`
}
// swagger:parameters datasourceProxyGETcalls datasourceProxyPOSTcalls datasourceProxyDELETEcalls
type DatasourceProxyRouteParam struct {
// in:path
// required:true
DatasourceProxyRoute string `json:"datasource_proxy_route"`
}
// swagger:parameters datasourceProxyPOSTcalls
type DatasourceProxyParam struct {
// in:body
// required:true
DatasourceProxyParam interface{}
}
// swagger:parameters addDatasource
type AddDatasourceParam struct {
// in:body
// required:true
Body models.AddDataSourceCommand
}
// swagger:parameters updateDatasource
type UpdateDatasource struct {
// in:body
// required:true
Body models.UpdateDataSourceCommand
}
// swagger:parameters queryDatasource
type QueryDatasource struct {
// in:body
// required:true
Body dtos.MetricRequest
}
// swagger:response getDatasourcesResponse
type GetDatasourcesResponse struct {
// The response message
// in: body
Body dtos.DataSourceList `json:"body"`
}
// swagger:response getDatasourceResponse
type GetDatasourceResponse struct {
// The response message
// in: body
Body dtos.DataSource `json:"body"`
}
// swagger:response createOrUpdateDatasourceResponse
type CreateOrUpdateDatasourceResponse struct {
// The response message
// in: body
Body struct {
// ID Identifier of the new data source.
// required: true
// example: 65
ID int64 `json:"id"`
// Name of the new data source.
// required: true
// example: My Data source
Name string `json:"name"`
// Message Message of the deleted dashboard.
// required: true
// example: Data source added
Message string `json:"message"`
// Datasource properties
// required: true
Datasource dtos.DataSource `json:"datasource"`
} `json:"body"`
}
// swagger:response getDatasourceIDresponse
type GetDatasourceIDresponse struct {
// The response message
// in: body
Body struct {
// ID Identifier of the data source.
// required: true
// example: 65
ID int64 `json:"id"`
} `json:"body"`
}
// swagger:response deleteDatasourceByNameResponse
type DeleteDatasourceByNameResponse struct {
// The response message
// in: body
Body struct {
// ID Identifier of the deleted data source.
// required: true
// example: 65
ID int64 `json:"id"`
// Message Message of the deleted dashboard.
// required: true
// example: Dashboard My Dashboard deleted
Message string `json:"message"`
} `json:"body"`
}
// swagger:response queryDatasourceResponse
type QueryDatasourceResponse struct {
// The response message
// in: body
//nolint: staticcheck // plugins.DataResponse deprecated
Body legacydata.DataResponse `json:"body"`
}

View File

@ -0,0 +1,34 @@
package definitions
import (
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana/pkg/api/dtos"
)
// swagger:route POST /ds/query ds queryMetricsWithExpressions
//
// Query metrics with expressions
//
// If you are running Grafana Enterprise and have Fine-grained access control enabled
// you need to have a permission with action: `datasources:query`.
//
// Responses:
// 200: queryDataResponse
// 401: unauthorisedError
// 400: badRequestError
// 403: forbiddenError
// 500: internalServerError
// swagger:parameters queryMetricsWithExpressions
type QueryMetricsWithExpressionsBodyParam struct {
// in:body
// required:true
Body dtos.MetricRequest `json:"body"`
}
// swagger:response queryDataResponse
type QueryDataResponseResponse struct {
// The response message
// in: body
Body *backend.QueryDataResponse `json:"body"`
}

View File

@ -0,0 +1,174 @@
package definitions
import (
"github.com/grafana/grafana/pkg/api/dtos"
"github.com/grafana/grafana/pkg/models"
)
// swagger:route GET /folders folders getFolders
//
// Get all folders.
//
// Returns all folders that the authenticated user has permission to view.
//
// Responses:
// 200: getFoldersResponse
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route GET /folders/{folder_uid} folders getFolderByUID
//
// Get folder by uid.
//
// Responses:
// 200:
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:route POST /folders folders createFolder
//
// Create folder.
//
// Responses:
// 200: folderResponse
// 400: badRequestError
// 401: unauthorisedError
// 403: forbiddenError
// 409: conflictError
// 500: internalServerError
// swagger:route PUT /folders/{folder_uid} folders updateFolder
//
// Update folder.
//
// Responses:
// 200: folderResponse
// 400: badRequestError
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 409: conflictError
// 500: internalServerError
// swagger:route DELETE /folders/{folder_uid} folders deleteFolder
//
// Delete folder.
//
// Deletes an existing folder identified by UID along with all dashboards (and their alerts) stored in the folder. This operation cannot be reverted.
//
// Responses:
// 200: deleteFolderResponse
// 400: badRequestError
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:route GET /folders/id/{folder_id} folders getFolderByID
//
// Get folder by id.
//
// Returns the folder identified by id.
//
// Responses:
// 200: folderResponse
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:parameters getFolders
type GetFoldersParams struct {
// Limit the maximum number of folders to return
// in:query
// required:false
// default:1000
Limit int64 `json:"limit"`
// Page index for starting fetching folders
// in:query
// required:false
// default:1
Page int64 `json:"page"`
}
// swagger:parameters getFolderByUID updateFolder deleteFolder
// swagger:parameters getFolderPermissions updateFolderPermissions
type FolderUIDParam struct {
// in:path
// required:true
FolderUID string `json:"folder_uid"`
}
// swagger:parameters getFolderByID
type FolderIDParam struct {
// in:path
// required:true
FolderID int64 `json:"folder_id"`
}
// swagger:parameters createFolder
type CreateFolderParam struct {
// in:body
// required:true
Body models.CreateFolderCommand `json:"body"`
}
// swagger:parameters updateFolder
type UpdateFolderParam struct {
// To change the unique identifier (uid), provide another one.
// To overwrite an existing folder with newer version, set `overwrite` to `true`.
// Provide the current version to safelly update the folder: if the provided version differs from the stored one the request will fail, unless `overwrite` is `true`.
//
// in:body
// required:true
Body models.UpdateFolderCommand `json:"body"`
}
// swagger:parameters deleteFolder
type DeleteFolderParam struct {
// If `true` any Grafana 8 Alerts under this folder will be deleted.
// Set to `false` so that the request will fail if the folder contains any Grafana 8 Alerts.
// in:query
// required:false
// default:false
ForceDeleteRules bool `json:"forceDeleteRules"`
}
// swagger:response getFoldersResponse
type GetFoldersResponse struct {
// The response message
// in: body
Body []dtos.FolderSearchHit `json:"body"`
}
// swagger:response folderResponse
type FolderResponse struct {
// The response message
// in: body
Body dtos.Folder `json:"body"`
}
// swagger:response deleteFolderResponse
type DeleteFolderResponse struct {
// The response message
// in: body
Body struct {
// ID Identifier of the deleted folder.
// required: true
// example: 65
ID int64 `json:"id"`
// Title of the deleted folder.
// required: true
// example: My Folder
Title string `json:"title"`
// Message Message of the deleted folder.
// required: true
// example: Folder My Folder deleted
Message string `json:"message"`
} `json:"body"`
}

View File

@ -0,0 +1,23 @@
package definitions
// swagger:route GET /folders/{folder_uid}/permissions folder_permissions getFolderPermissions
//
// Gets all existing permissions for the folder with the given `uid`.
//
// Responses:
// 200: getDashboardPermissionsResponse
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:route POST /folders/{folder_uid}/permissions folder_permissions updateFolderPermissions
//
// Updates permissions for a folder. This operation will remove existing permissions if theyre not included in the request.
//
// Responses:
// 200: okResponse
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError

View File

@ -0,0 +1,217 @@
package definitions
import (
"github.com/grafana/grafana/pkg/api/dtos"
"github.com/grafana/grafana/pkg/models"
)
// swagger:route GET /alert-notifications legacy_alerts_notification_channels getAlertNotificationChannels
//
// Get all notification channels.
//
// Returns all notification channels that the authenticated user has permission to view.
//
// Responses:
// 200: getAlertNotificationChannelsResponse
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route GET /alert-notifications/lookup legacy_alerts_notification_channels lookupAlertNotificationChannels
//
// Get all notification channels (lookup)
//
// Returns all notification channels, but with less detailed information. Accessible by any authenticated user and is mainly used by providing alert notification channels in Grafana UI when configuring alert rule.
//
// Responses:
// 200: lookupAlertNotificationChannelsResponse
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route POST /alert-notifications/test legacy_alerts_notification_channels notificationChannelTest
//
// Test notification channel.
//
// Sends a test notification to the channel.
//
// Responses:
// 200: okResponse
// 400: badRequestError
// 401: unauthorisedError
// 403: forbiddenError
// 412: SMTPNotEnabledError
// 500: internalServerError
// swagger:route POST /alert-notifications legacy_alerts_notification_channels createAlertNotificationChannel
//
// Create notification channel.
//
// You can find the full list of [supported notifiers](https://grafana.com/docs/grafana/latest/alerting/old-alerting/notifications/#list-of-supported-notifiers) on the alert notifiers page.
//
// Responses:
// 200: getAlertNotificationChannelResponse
// 401: unauthorisedError
// 403: forbiddenError
// 409: conflictError
// 500: internalServerError
// swagger:route PUT /alert-notifications/{notification_channel_id} legacy_alerts_notification_channels updateAlertNotificationChannel
//
// Update notification channel by ID.
//
// Updates an existing notification channel identified by ID.
//
// Responses:
// 200: getAlertNotificationChannelResponse
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:route GET /alert-notifications/{notification_channel_id} legacy_alerts_notification_channels getAlertNotificationChannelByID
//
// Get notification channel by ID.
//
// Returns the notification channel given the notification channel ID.
//
// Responses:
// 200: getAlertNotificationChannelResponse
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:route DELETE /alert-notifications/{notification_channel_id} legacy_alerts_notification_channels deleteAlertNotificationChannel
//
// Delete alert notification by ID.
//
// Deletes an existing notification channel identified by ID.
//
// Responses:
// 200: okResponse
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:route GET /alert-notifications/uid/{notification_channel_uid} legacy_alerts_notification_channels getAlertNotificationChannelByUID
//
// Get notification channel by UID
//
// Returns the notification channel given the notification channel UID.
//
// Responses:
// 200: getAlertNotificationChannelResponse
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:route PUT /alert-notifications/uid/{notification_channel_uid} legacy_alerts_notification_channels updateAlertNotificationChannelBYUID
//
// Update notification channel by UID.
//
// Updates an existing notification channel identified by uid.
//
// Responses:
// 200: getAlertNotificationChannelResponse
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:route DELETE /alert-notifications/uid/{notification_channel_uid} legacy_alerts_notification_channels deleteAlertNotificationChannelByUID
//
// Delete alert notification by UID.
//
// Deletes an existing notification channel identified by UID.
//
// Responses:
// 200: deleteAlertNotificationChannelResponse
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:parameters updateAlertNotificationChannel getAlertNotificationChannelByID deleteAlertNotificationChannel
type NotificationIDParam struct {
// in:path
// required:true
NotificationID int64 `json:"notification_channel_id"`
}
// swagger:parameters getAlertNotificationChannelByUID updateAlertNotificationChannelBYUID deleteAlertNotificationChannelByUID
type NotificationUIDParam struct {
// in:path
// required:true
NotificationUID string `json:"notification_channel_uid"`
}
// swagger:parameters notificationChannelTest
type NotificationChannelTestParam struct {
// in:body
// required:true
Body dtos.NotificationTestCommand `json:"body"`
}
// swagger:parameters createAlertNotificationChannel
type CreateAlertNotificationChannelParam struct {
// in:body
// required:true
Body models.CreateAlertNotificationCommand `json:"body"`
}
// swagger:parameters updateAlertNotificationChannel
type UpdateAlertNotificationChannelParam struct {
// in:body
// required:true
Body models.UpdateAlertNotificationCommand `json:"body"`
}
// swagger:parameters updateAlertNotificationChannelBYUID
type UpdateAlertNotificationChannelBYUIDParam struct {
// in:body
// required:true
Body models.UpdateAlertNotificationWithUidCommand `json:"body"`
}
// swagger:response getAlertNotificationChannelsResponse
type GetAlertNotificationChannelsResponse struct {
// The response message
// in: body
Body []*dtos.AlertNotification `json:"body"`
}
// swagger:response lookupAlertNotificationChannelsResponse
type LookupAlertNotificationChannelsResponse struct {
// The response message
// in: body
Body []*dtos.AlertNotificationLookup `json:"body"`
}
// swagger:response getAlertNotificationChannelResponse
type GetAlertNotificationChannelResponse struct {
// The response message
// in: body
Body *dtos.AlertNotification `json:"body"`
}
// swagger:response deleteAlertNotificationChannelResponse
type DeleteAlertNotificationChannelResponse struct {
// The response message
// in: body
Body struct {
// ID Identifier of the deleted notification channel.
// required: true
// example: 65
ID int64 `json:"id"`
// Message Message of the deleted notificatiton channel.
// required: true
Message string `json:"message"`
} `json:"body"`
}
// swagger:response SMTPNotEnabledError
type SMTPNotEnabledError PreconditionFailedError

View File

@ -0,0 +1,177 @@
package definitions
import (
"github.com/grafana/grafana/pkg/api/dtos"
"github.com/grafana/grafana/pkg/models"
)
// swagger:route GET /alerts legacy_alerts getAlerts
//
// Get legacy alerts.
//
// Responses:
// 200: getAlertsResponse
// 401: unauthorisedError
// 500: internalServerError
// swagger:route GET /alerts/{alert_id} legacy_alerts getAlertByID
//
// Get alert by ID.
//
// “evalMatches” data in the response is cached in the db when and only when the state of the alert changes (e.g. transitioning from “ok” to “alerting” state).
// If data from one server triggers the alert first and, before that server is seen leaving alerting state, a second server also enters a state that would trigger the alert, the second server will not be visible in “evalMatches” data.
//
// Responses:
// 200: getAlertResponse
// 401: unauthorisedError
// 500: internalServerError
// swagger:route POST /alerts/{alert_id}/pause legacy_alerts pauseAlert
//
// Pause/unpause alert by id.
//
// Responses:
// 200: pauseAlertResponse
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:route POST /alerts/test legacy_alerts testAlert
//
// Test alert.
//
// Responses:
// 200: testAlertResponse
// 400: badRequestError
// 422: unprocessableEntityError
// 403: forbiddenError
// 500: internalServerError
// swagger:route GET /alerts/states-for-dashboard legacy_alerts getDashboardStates
//
// Get alert states for a dashboard.
//
// Responses:
// Responses:
// 200: getDashboardStatesResponse
// 400: badRequestError
// 500: internalServerError
// swagger:parameters getAlertByID pauseAlert
type AlertIDParam struct {
// in:path
// required:true
AlertID string `json:"alert_id"`
}
// swagger:parameters pauseAlert
type PauseAlertParam struct {
// in:body
// required:true
Body dtos.PauseAlertCommand `json:"body"`
}
// swagger:parameters getAlerts
type GetAlertsParams struct {
// Limit response to alerts in specified dashboard(s). You can specify multiple dashboards.
// in:query
// required:false
DashboardID []string `json:"dashboardId"`
// Limit response to alert for a specified panel on a dashboard.
// in:query
// required:false
PanelID int64 `json:"panelId"`
// Limit response to alerts having a name like this value.
// in:query
// required: false
Query string `json:"query"`
// Return alerts with one or more of the following alert states
// in:query
// required:false
// Description:
// * `all`
// * `no_data`
// * `paused`
// * `alerting`
// * `ok`
// * `pending`
// * `unknown`
// enum: all,no_data,paused,alerting,ok,pending,unknown
State string `json:"state"`
// Limit response to X number of alerts.
// in:query
// required:false
Limit int64 `json:"limit"`
// Limit response to alerts of dashboards in specified folder(s). You can specify multiple folders
// in:query
// required:false
// type array
// collectionFormat: multi
FolderID []string `json:"folderId"`
// Limit response to alerts having a dashboard name like this value./ Limit response to alerts having a dashboard name like this value.
// in:query
// required:false
DashboardQuery string `json:"dashboardQuery"`
// Limit response to alerts of dashboards with specified tags. To do an “AND” filtering with multiple tags, specify the tags parameter multiple times
// in:query
// required:false
// type: array
// collectionFormat: multi
DashboardTag []string `json:"dashboardTag"`
}
// swagger:parameters testAlert
type TestAlertParam struct {
// in:body
Body dtos.AlertTestCommand `json:"body"`
}
// swagger:parameters getDashboardStates
type GetDashboardStatesParam struct {
// in:query
// required: true
DashboardID int64 `json:"dashboardId"`
}
// swagger:response getAlertsResponse
type GetAlertsResponse struct {
// The response message
// in: body
Body []*models.AlertListItemDTO `json:"body"`
}
// swagger:response getAlertResponse
type GetAlertResponse struct {
// The response message
// in: body
Body []*models.Alert `json:"body"`
}
// swagger:response pauseAlertResponse
type PauseAlertResponse struct {
// in:body
Body struct {
// required: true
AlertID int64 `json:"alertId"`
// required: true
Message string `json:"message"`
// Alert result state
// required true
State string `json:"state"`
} `json:"body"`
}
// swagger:response testAlertResponse
type TestAlertResponse struct {
// The response message
// in: body
Body *dtos.AlertTestResult `json:"body"`
}
// swagger:response getDashboardStatesResponse
type GetDashboardStatesResponse struct {
// The response message
// in: body
Body []*models.AlertStateInfoDTO `json:"body"`
}

View File

@ -0,0 +1,190 @@
package definitions
import (
"github.com/grafana/grafana/pkg/services/libraryelements"
)
// swagger:route GET /library-elements library_elements getLibraryElements
//
// Get all library elements.
//
// Returns a list of all library elements the authenticated user has permission to view.
// Use the `perPage` query parameter to control the maximum number of library elements returned; the default limit is `100`.
// You can also use the `page` query parameter to fetch library elements from any page other than the first one.
//
// Responses:
// 200: getLibraryElementsResponse
// 401: unauthorisedError
// 500: internalServerError
// swagger:route GET /library-elements/{library_element_uid} library_elements getLibraryElementByUID
//
// Get library element by UID.
//
// Returns a library element with the given UID.
//
// Responses:
// 200: getLibraryElementResponse
// 401: unauthorisedError
// 404: notFoundError
// 500: internalServerError
// swagger:route GET /library-elements/name/{library_element_name} library_elements getLibraryElementByName
//
// Get library element by name.
//
// Returns a library element with the given name.
//
// Responses:
// 200: getLibraryElementResponse
// 401: unauthorisedError
// 404: notFoundError
// 500: internalServerError
// swagger:route GET /library-elements/{library_element_uid}/connections/ library_elements getLibraryElementConnections
//
// Get library element connections.
//
// Returns a list of connections for a library element based on the UID specified.
//
// Responses:
// 200: getLibraryElementConnectionsResponse
// 401: unauthorisedError
// 404: notFoundError
// 500: internalServerError
// swagger:route POST /library-elements library_elements createLibraryElement
//
// Create library element.
//
// Creates a new library element.
//
// Responses:
// 200: getLibraryElementResponse
// 400: badRequestError
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:route PATCH /library-elements/{library_element_uid} library_elements updateLibraryElement
//
// Update library element.
//
// Updates an existing library element identified by uid.
//
// Responses:
// 200: getLibraryElementResponse
// 400: badRequestError
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 412: preconditionFailedError
// 500: internalServerError
// swagger:route DELETE /library-elements/{library_element_uid} library_elements deleteLibraryElementByUID
//
// Delete library element.
//
// Deletes an existing library element as specified by the UID. This operation cannot be reverted.
// You cannot delete a library element that is connected. This operation cannot be reverted.
//
// Responses:
// 200: okResponse
// 400: badRequestError
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:parameters getLibraryElementByUID getLibraryElementConnections updateLibraryElement deleteLibraryElementByUID
type LibraryElementByUID struct {
// in:path
// required:true
UID string `json:"library_element_uid"`
}
// swagger:parameters getLibraryElementByName
type LibraryElementByName struct {
// in:path
// required:true
Name string `json:"library_element_name"`
}
// swagger:parameters getLibraryElements
type GetLibraryElementsParams struct {
// Part of the name or description searched for.
// in:query
// required:false
SearchString string `json:"searchString"`
// Kind of element to search for.
// in:query
// required:false
// Description:
// * 1 - library panels
// * 2 - library variables
// enum: 1,2
Kind int `json:"kind"`
// Sort order of elements.
// in:query
// required:false
// Description:
// * alpha-asc: ascending
// * alpha-desc: descending
// Enum: alpha-asc,alpha-desc
SortDirection string `json:"sortDirection"`
// A comma separated list of types to filter the elements by
// in:query
// required:false
TypeFilter string `json:"typeFilter"`
// Element UID to exclude from search results.
// in:query
// required:false
ExcludeUID string `json:"excludeUid"`
// A comma separated list of folder ID(s) to filter the elements by.
// in:query
// required:false
FolderFilter string `json:"folderFilter"`
// The number of results per page.
// in:query
// required:false
// default: 100
PerPage int `json:"perPage"`
// The page for a set of records, given that only perPage records are returned at a time. Numbering starts at 1.
// in:query
// required:false
// default: 1
Page int `json:"page"`
}
// swagger:parameters createLibraryElement
type CreateLibraryElementParam struct {
// in:body
// required:true
Body libraryelements.CreateLibraryElementCommand `json:"body"`
}
// swagger:parameters updateLibraryElement
type UpdateLibraryElementParam struct {
// in:body
// required:true
Body libraryelements.PatchLibraryElementCommand `json:"body"`
}
// swagger:response getLibraryElementsResponse
type GetLibraryElementsResponse struct {
// in: body
Body libraryelements.LibraryElementSearchResponse `json:"body"`
}
// swagger:response getLibraryElementResponse
type GetLibraryElementResponse struct {
// in: body
Body libraryelements.LibraryElementResponse `json:"body"`
}
// swagger:response getLibraryElementConnectionsResponse
type GetLibraryElementConnectionsResponse struct {
// in: body
Body libraryelements.LibraryElementConnectionsResponse `json:"body"`
}

View File

@ -0,0 +1,31 @@
// Package api Grafana HTTP API.
//
// The Grafana backend exposes an HTTP API, the same API is used by the frontend to do
// everything from saving dashboards, creating users and updating data sources.
//
// Schemes: http, https
// BasePath: /api
// Version: 0.0.1
// License: GNU Affero General Public License v3.0 https://www.gnu.org/licenses/agpl-3.0.en.html
// Contact: Grafana Labs<hello@grafana.com> https://grafana.com
//
// Consumes:
// - application/json
//
// Produces:
// - application/json
//
// Security:
// - basic:
// - api_key:
//
// SecurityDefinitions:
// basic:
// type: basic
// api_key:
// type: apiKey
// name: Authorization
// in: header
//
// swagger:meta
package definitions

View File

@ -0,0 +1,185 @@
package definitions
import (
"github.com/grafana/grafana/pkg/api/dtos"
"github.com/grafana/grafana/pkg/models"
)
// swagger:route GET /org current_org_details getOrg
//
// Get current Organization
//
// Responses:
// 200: getOrgResponse
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route GET /org/users current_org_details getOrgUsers
//
// Get all users within the current organization.
//
// Returns all org users within the current organization. Accessible to users with org admin role.
// If you are running Grafana Enterprise and have Fine-grained access control enabled
// you need to have a permission with action: `org.users:read` with scope `users:*`.
//
// Responses:
// 200: getOrgUsersResponse
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route GET /org/users/lookup current_org_details lookupOrgUsers
//
// Get all users within the current organization (lookup)
//
// Returns all org users within the current organization, but with less detailed information.
// Accessible to users with org admin role, admin in any folder or admin of any team.
// Mainly used by Grafana UI for providing list of users when adding team members and when editing folder/dashboard permissions.
//
// Responses:
// 200: lookupOrgUsersResponse
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route PATCH /org/users/{user_id} current_org_details updateOrgUser
//
// Updates the given user
//
// If you are running Grafana Enterprise and have Fine-grained access control enabled
// you need to have a permission with action: `org.users.role:update` with scope `users:*`.
//
// Responses:
// 200: okResponse
// 400: badRequestError
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route DELETE /org/users/{user_id} current_org_details deleteOrgUser
//
// Delete user in current organization
//
// If you are running Grafana Enterprise and have Fine-grained access control enabled
// you need to have a permission with action: `org.users:remove` with scope `users:*`.
//
// Responses:
// 200: okResponse
// 400: badRequestError
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route PUT /org current_org_details updateOrg
//
// Update current Organization.
//
// Responses:
// 200: okResponse
// 400: badRequestError
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route PUT /org/address current_org_details updateOrgAddress
//
// Update current Organization's address.
//
// Responses:
// 200: okResponse
// 400: badRequestError
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route POST /org/users current_org_details addOrgUser
//
// Add a new user to the current organization
//
// Adds a global user to the current organization.
//
// If you are running Grafana Enterprise and have Fine-grained access control enabled
// you need to have a permission with action: `org.users:add` with scope `users:*`.
//
// Responses:
// 200: okResponse
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:parameters updateOrgAddress adminUpdateOrgAddress
type UpdateOrgAddressParam struct {
// in:body
// required:true
Body dtos.UpdateOrgAddressForm `json:"body"`
}
// swagger:parameters updateOrgUser adminUpdateOrgUser
type UpdateOrgUserParam struct {
// in:body
// required:true
Body models.UpdateOrgUserCommand `json:"body"`
}
// swagger:parameters updateOrg adminUpdateOrg
type UpdateOrgParam struct {
// in:body
// required:true
Body dtos.UpdateOrgForm `json:"body"`
}
// swagger:parameters addOrgUser adminAddOrgUser
type AddOrgUserParam struct {
// in:body
// required:true
Body models.AddOrgUserCommand `json:"body"`
}
// swagger:parameters lookupOrgUsers
type LookupOrgUsersParams struct {
// in:query
// required:false
Query string `json:"query"`
// in:query
// required:false
Limit int `json:"limit"`
}
// swagger:response getOrgResponse
type GetOrgResponse struct {
// The response message
// in: body
Body models.OrgDetailsDTO `json:"body"`
}
// swagger:response getOrgUsersResponse
type GetOrgUsersResponse struct {
// The response message
// in: body
Body []*models.OrgUserDTO `json:"body"`
}
// swagger:response lookupOrgUsersResponse
type LookupOrgUsersResponse struct {
// The response message
// in: body
Body []*dtos.UserLookupDTO `json:"body"`
}
// swagger:response addOrgUser
type AddOrgUser struct {
// The response message
// in: body
Body struct {
// ID Identifier of the added user.
// required: true
// example: 65
UsedID int64 `json:"id"`
// Message Message of the added user.
// required: true
// example: Data source added
Message string `json:"message"`
} `json:"body"`
}

View File

@ -0,0 +1,60 @@
package definitions
import (
"github.com/grafana/grafana/pkg/api/dtos"
"github.com/grafana/grafana/pkg/models"
)
// swagger:route GET /org/invites org_invites getInvites
//
// Get pending invites.
//
// Responses:
// 200: getInvitesResponse
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route POST /org/invites org_invites addInvite
//
// Add invite.
//
// Responses:
// 200: addOrgUser
// 400: badRequestError
// 401: unauthorisedError
// 403: forbiddenError
// 412: SMTPNotEnabledError
// 500: internalServerError
// swagger:route DELETE /org/{invitation_code}/invites org_invites revokeInvite
//
// Revoke invite.
//
// Responses:
// 200: okResponse
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:parameters addInvite
type AddInviteParam struct {
// in:body
// required:true
Body dtos.AddInviteForm `json:"body"`
}
// swagger:parameters revokeInvite
type RevokeInviteParam struct {
// in:path
// required:true
Code string `json:"invitation_code"`
}
// swagger:response getInvitesResponse
type GetInvitesResponse struct {
// The response message
// in: body
Body []*models.TempUserDTO `json:"body"`
}

View File

@ -0,0 +1,22 @@
package definitions
// swagger:route GET /org/preferences org_preferences getOrgPreferences
//
// Get Current Org Prefs.
//
// Responses:
// 200: getPreferencesResponse
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route PUT /org/preferences org_preferences updateOrgPreferences
//
// Update Current Org Prefs.
//
// Responses:
// 200: addOrgUser
// 400: badRequestError
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError

View File

@ -0,0 +1,256 @@
package definitions
import "github.com/grafana/grafana/pkg/models"
// swagger:route GET /orgs/{org_id} orgs getOrgByID
//
// Get Organization by ID.
//
// Security:
// - basic:
//
// Responses:
// 200: getOrgResponse
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route GET /orgs/name/{org_name} orgs getOrgByName
//
// Get Organization by ID.
//
// Security:
// - basic:
//
// Responses:
// 200: getOrgResponse
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route POST /orgs orgs createOrg
//
// Create Organization.
//
// Only works if [users.allow_org_create](https://grafana.com/docs/grafana/latest/administration/configuration/#allow_org_create) is set.
//
// Responses:
// 200: createOrgResponse
// 401: unauthorisedError
// 403: forbiddenError
// 409: conflictError
// 500: internalServerError
// swagger:route GET /orgs orgs searchOrg
//
// Search all Organizations
//
// Security:
// - basic:
//
// Responses:
// 200: searchOrgResponse
// 401: unauthorisedError
// 403: forbiddenError
// 409: conflictError
// 500: internalServerError
// swagger:route PUT /orgs/{org_id} orgs adminUpdateOrg
//
// Update Organization.
//
// Security:
// - basic:
//
// Responses:
// 200: okResponse
// 400: badRequestError
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route PUT /orgs/{org_id}/address orgs adminUpdateOrgAddress
//
// Update Organization's address.
//
// Responses:
// 200: okResponse
// 400: badRequestError
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route DELETE /orgs/{org_id} orgs adminDeleteOrg
//
// Delete Organization.
//
// Security:
// - basic:
//
// Responses:
// 200: okResponse
// 400: badRequestError
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:route GET /orgs/{org_id}/users orgs adminGetOrgUsers
//
// Get Users in Organization.
//
// If you are running Grafana Enterprise and have Fine-grained access control enabled
// you need to have a permission with action: `org.users:read` with scope `users:*`.
//
// Security:
// - basic:
//
// Responses:
// 200: getOrgUsersResponse
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route POST /orgs/{org_id}/users orgs adminAddOrgUser
//
// Add a new user to the current organization
//
// Adds a global user to the current organization.
//
// If you are running Grafana Enterprise and have Fine-grained access control enabled
// you need to have a permission with action: `org.users:add` with scope `users:*`.
//
// Responses:
// 200: okResponse
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route PATCH /orgs/{org_id}/users/{user_id} orgs adminUpdateOrgUser
//
// Update Users in Organization.
//
// If you are running Grafana Enterprise and have Fine-grained access control enabled
// you need to have a permission with action: `org.users.role:update` with scope `users:*`.
//
// Responses:
// 200: okResponse
// 400: badRequestError
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route DELETE /orgs/{org_id}/users/{user_id} orgs adminDeleteOrgUser
//
// Delete user in current organization
//
// If you are running Grafana Enterprise and have Fine-grained access control enabled
// you need to have a permission with action: `org.users:remove` with scope `users:*`.
//
// Responses:
// 200: okResponse
// 400: badRequestError
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route GET /orgs/{org_id}/quotas orgs getOrgQuota
//
// Fetch Organization quota.
//
// If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `orgs.quotas:read` and scope `org:id:1` (orgIDScope).
//list
// Responses:
// 200: getQuotaResponse
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:route PUT /orgs/{org_id}/quotas/{quota_target} orgs updateOrgQuota
//
// Update user quota.
//
// If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `orgs.quotas:write` and scope `org:id:1` (orgIDScope).
//
// Security:
// - basic:
//
// Responses:
// 200: okResponse
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:parameters getOrgByID adminUpdateOrg adminUpdateOrgAddress adminDeleteOrg adminGetOrgUsers
// swagger:parameters adminAddOrgUser adminUpdateOrgUser adminDeleteOrgUser
// swagger:parameters getOrgQuota updateOrgQuota userSetUsingOrg
type OrgIDParam struct {
// in:path
// required:true
OrgID int64 `json:"org_id"`
}
// swagger:parameters getOrgByName
type OrgNameParam struct {
// in:path
// required:true
OrgName string `json:"org_name"`
}
// swagger:parameters createOrg
type CreateOrgParam struct {
// in:body
// required:true
Body models.CreateOrgCommand `json:"body"`
}
// swagger:parameters searchOrg searchTeams
type SearchOrgParams struct {
// in:query
// required:false
// default: 1
Page int `json:"page"`
// Number of items per page
// The totalCount field in the response can be used for pagination list E.g. if totalCount is equal to 100 teams and the perpage parameter is set to 10 then there are 10 pages of teams.
// in:query
// required:false
// default: 1000
PerPage int `json:"perpage"`
Name string `json:"name"`
// If set it will return results where the query value is contained in the name field. Query values with spaces need to be URL encoded.
// required:false
Query string `json:"query"`
}
// swagger:parameters updateOrgQuota
type UpdateOrgQuotaParam struct {
// in:body
// required:true
Body models.UpdateOrgQuotaCmd `json:"body"`
}
// swagger:response createOrgResponse
type CreateOrgResponse struct {
// The response message
// in: body
Body struct {
// ID Identifier of the created org.
// required: true
// example: 65
OrgID int64 `json:"orgId"`
// Message Message of the created org.
// required: true
// example: Data source added
Message string `json:"message"`
} `json:"body"`
}
// swagger:response searchOrgResponse
type SearchOrgResponse struct {
// The response message
// in: body
Body []*models.OrgDTO `json:"body"`
}

View File

@ -0,0 +1,83 @@
package definitions
// A GenericError is the default error message that is generated.
// For certain status codes there are more appropriate error structures.
//
// swagger:response genericError
type GenericError struct {
// The response message
// in: body
Body ErrorResponseBody `json:"body"`
}
type ErrorResponseBody struct {
// a human readable version of the error
// required: true
Message string `json:"message"`
// Error An optional detailed description of the actual error. Only included if running in developer mode.
Error string `json:"error"`
// Status An optional status to denote the cause of the error.
//
// For example, a 412 Precondition Failed error may include additional information of why that error happened.
Status string `json:"status"`
}
// swagger:model
type SuccessResponseBody struct {
Message string `json:"message,omitempty"`
}
// An OKResponse is returned if the request was successful.
//
// swagger:response okResponse
type OKResponse struct {
// in: body
Body SuccessResponseBody `json:"body"`
}
// ForbiddenError is returned if the user/token has insufficient permissions to access the requested resource.
//
// swagger:response forbiddenError
type ForbiddenError GenericError
// NotFoundError is returned when the requested resource was not found.
//
// swagger:response notFoundError
type NotFoundError GenericError
// BadRequestError is returned when the request is invalid and it cannot be processed.
//
// swagger:response badRequestError
type BadRequestError GenericError
// ConflictError
//
// swagger:response conflictError
type ConflictError GenericError
// PreconditionFailedError
//
// swagger:response preconditionFailedError
type PreconditionFailedError GenericError
// UnprocessableEntityError
//
// swagger:response unprocessableEntityError
type UnprocessableEntityError GenericError
// InternalServerError is a general error indicating something went wrong internally.
//
// swagger:response internalServerError
type InternalServerError GenericError
// UnauthorizedError is returned when the request is not authenticated.
//
// swagger:response unauthorisedError
type UnauthorizedError GenericError
// AcceptedResponse
//
// swagger:response acceptedResponse
type AcceptedResponse GenericError

View File

@ -0,0 +1,90 @@
package definitions
import "github.com/grafana/grafana/pkg/services/search"
// swagger:route GET /search/sorting search searchSorting
//
// List search sorting options
//
// Responses:
// 200: searchSortingResponse
// 401: unauthorisedError
// swagger:route GET /search search search
//
// Responses:
// 200: searchResponse
// 401: unauthorisedError
// 422: unprocessableEntityError
// 500: internalServerError
// swagger:parameters search
type SearchParameters struct {
// Search Query
// in:query
// required: false
Query string `json:"query"`
// List of tags to search for
// in:query
// required: false
// type: array
// collectionFormat: multi
Tag []string `json:"tag"`
// Type to search for, dash-folder or dash-db
// in:query
// required: false
// Description:
// * `dash-folder` - Search for folder
// * `dash-db` - Seatch for dashboard
// Enum: dash-folder,dash-db
Type string `json:"type"`
// List of dashboard ids to search for
// in:query
// required: false
DashboardIds []int64 `json:"dashboardIds"`
// List of folder ids to search in for dashboards
// in:query
// required: false
FolderIds []int64 `json:"folderIds"`
// Flag indicating if only starred Dashboards should be returned
// in:query
// required: false
Starred bool `json:"starred"`
// Limit the number of returned results (max 5000)
// in:query
// required: false
Limit int64 `json:"limit"`
// Use this parameter to access hits beyond limit. Numbering starts at 1. limit param acts as page size. Only available in Grafana v6.2+.
// in:query
// required: false
Page int64 `json:"page"`
// Set to `Edit` to return dashboards/folders that the user can edit
// in:query
// required: false
// default:View
// Enum: Edit,View
Permission string `json:"permission"`
// Sort method; for listing all the possible sort methods use the search sorting endpoint.
// in:query
// required: false
// default: alpha-asc
// Enum: alpha-asc,alpha-desc
Sort string `json:"sort"`
}
// swagger:response searchResponse
type SearchResponse struct {
// in: body
Body search.HitList `json:"body"`
}
// swagger:response searchSortingResponse
type SearchSortingResponse struct {
// in: body
Body struct {
Name string `json:"name"`
DisplayName string `json:"displayName"`
Description string `json:"description"`
Meta string `json:"meta"`
} `json:"body"`
}

View File

@ -0,0 +1,129 @@
package definitions
import (
"github.com/grafana/grafana/pkg/models"
)
// swagger:route POST /snapshots snapshots createSnapshot
//
// When creating a snapshot using the API, you have to provide the full dashboard payload including the snapshot data. This endpoint is designed for the Grafana UI.
//
// Snapshot public mode should be enabled or authentication is required.
//
// Responses:
// 200: createSnapshotResponse
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route GET /dashboard/snapshots snapshots getSnapshots
//
// List snapshots.
//
// Responses:
// 200: getSnapshotsResponse
// 500: internalServerError
// swagger:route GET /snapshots/{key} snapshots getSnapshotByKey
//
// Get Snapshot by Key.
//
// Responses:
// 200: snapshotResponse
// 404: notFoundError
// 500: internalServerError
// swagger:route DELETE /snapshots/{key} snapshots deleteSnapshotByKey
//
// Delete Snapshot by Key.
//
// Responses:
// 200: okResponse
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:route GET /snapshots-delete/{deleteKey} snapshots deleteSnapshotByDeleteKey
//
// Delete Snapshot by deleteKey.
//
// Snapshot public mode should be enabled or authentication is required.
//
// Responses:
// 200: okResponse
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:route GET /snapshot/shared-options snapshots getSnapshotSharingOptions
//
// Get snapshot sharing settings.
//
// Responses:
// 200: getSnapshotSharingOptionsResponse
// 401: unauthorisedError
// swagger:parameters createSnapshot
type CreateSnapshotParam struct {
// in:body
// required:true
Body models.CreateDashboardSnapshotCommand `json:"body"`
}
// swagger:parameters getSnapshots
type GetSnapshotsParams struct {
// Search Query
// in:query
Query string `json:"query"`
// Limit the number of returned results
// in:query
// default:1000
Limit int64 `json:"limit"`
}
// swagger:parameters getSnapshotByKey deleteSnapshotByKey
type SnapshotByKeyParam struct {
// in:path
Key string `json:"key"`
}
// swagger:parameters deleteSnapshotByDeleteKey
type DeleteSnapshotByDeleteKeyParam struct {
// in:path
DeleteKey string `json:"deleteKey"`
}
// swagger:response createSnapshotResponse
type CreateSnapshotResponse struct {
// in:body
Body struct {
// Unique key
Key string `json:"key"`
// Unique key used to delete the snapshot. It is different from the key so that only the creator can delete the snapshot.
DeleteKey string `json:"deleteKey"`
URL string `json:"url"`
DeleteUrl string `json:"deleteUrl"`
// Snapshot id
ID int64 `json:"id"`
} `json:"body"`
}
// swagger:response getSnapshotsResponse
type GetSnapshotsResponse struct {
// in:body
Body []*models.DashboardSnapshotDTO `json:"body"`
}
// swagger:response snapshotResponse
type SnapshotResponse DashboardResponse
// swagger:response getSnapshotSharingOptionsResponse
type GetSnapshotSharingOptionsResponse struct {
// in:body
Body struct {
ExternalSnapshotURL string `json:"externalSnapshotURL"`
ExternalSnapshotName string `json:"externalSnapshotName"`
ExternalEnabled bool `json:"externalEnabled"`
} `json:"body"`
}

View File

@ -0,0 +1,188 @@
package definitions
import "github.com/grafana/grafana/pkg/models"
// swagger:route GET /teams/search teams searchTeams
//
// Team Search With Paging.
//
// Responses:
// 200: searchTeamsResponse
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route POST /teams teams createTeam
//
// Add Team.
//
// Responses:
// 200: createTeamResponse
// 401: unauthorisedError
// 403: forbiddenError
// 409: conflictError
// 500: internalServerError
// swagger:route GET /teams/{team_id} teams getTeam
//
// Get Team By ID.
//
// Responses:
// 200: getTeamResponse
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:route PUT /teams/{team_id} teams updateTeam
//
// Update Team.
//
// Responses:
// 200: okResponse
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 409: conflictError
// 500: internalServerError
// swagger:route DELETE /teams/{team_id} teams deleteTeamByID
//
// Delete Team By ID.
//
// Responses:
// 200: okResponse
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:route GET /teams/{team_id}/members teams getTeamMembers
//
// Get Team Members.
//
// Responses:
// 200: okResponse
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:route POST /teams/{team_id}/members teams addTeamMember
//
// Add Team Member.
//
// Responses:
// 200: okResponse
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:route PUT /teams/{team_id}/members/{user_id} teams updateTeamMember
//
// Update Team Member.
//
// Responses:
// 200: okResponse
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:route DELETE /teams/{team_id}/members/{user_id} teams removeTeamMember
//
// Remove Member From Team.
//
// Responses:
// 200: okResponse
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:route GET /teams/{team_id}/preferences teams getTeamPreferences
//
// Get Team Preferences.
//
// Responses:
// 200: getPreferencesResponse
// 401: unauthorisedError
// 500: internalServerError
// swagger:route PUT /teams/{team_id}/preferences teams updateTeamPreferences
//
// Update Team Preferences.
//
// Responses:
// 200: okResponse
// 400: badRequestError
// 401: unauthorisedError
// 500: internalServerError
// swagger:parameters getTeam updateTeam deleteTeamByID getTeamMembers addTeamMember updateTeamMember
// swagger:parameters removeTeamMember getTeamPreferences updateTeamPreferences
type TeamIDParam struct {
// in:path
// required:true
TeamID string `json:"team_id"`
}
// swagger:parameters createTeam
type CreateTeamParam struct {
// in:body
// required:true
Body models.CreateTeamCommand `json:"body"`
}
// swagger:parameters updateTeam
type UpdateTeamParam struct {
// in:body
// required:true
Body models.UpdateTeamCommand `json:"body"`
}
// swagger:parameters addTeamMemberTeam
type AddTeamMemberParam struct {
// in:body
// required:true
Body models.AddTeamMemberCommand `json:"body"`
}
// swagger:parameters updateTeamMember
type UpdateTeamMember struct {
// in:body
// required:true
Body models.UpdateTeamMemberCommand `json:"body"`
}
// swagger:response searchTeamsResponse
type SearchTeamsResponse struct {
// The response message
// in: body
Body models.SearchTeamQueryResult `json:"body"`
}
// swagger:response getTeamResponse
type GetTeamResponse struct {
// The response message
// in: body
Body *models.TeamDTO `json:"body"`
}
// swagger:response createTeamResponse
type CreateTeamResponse struct {
// The response message
// in: body
Body struct {
TeamId int64 `json:"teamId"`
Message string `json:"message"`
} `json:"body"`
}
// swagger:response getTeamMembersResponse
type GetTeamMembersResponse struct {
// The response message
// in: body
Body []*models.TeamMemberDTO `json:"body"`
}

View File

@ -0,0 +1,194 @@
package definitions
import "github.com/grafana/grafana/pkg/models"
// swagger:route GET /user signed_in_user getSignedInUser
//
// Get signed in User.
//
// Responses:
// 200: userResponse
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:route PUT /user signed_in_user updateSignedInUser
//
// Update signed in User.
//
// Responses:
// 200: userResponse
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route POST /user/using/{org_id} signed_in_user userSetUsingOrg
//
// Switch user context for signed in user.
//
// Switch user context to the given organization.
//
// Responses:
// 200: okResponse
// 400: badRequestError
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route GET /user/orgs signed_in_user getSignedInUserOrgList
//
// Organizations of the actual User.
//
// Return a list of all organizations of the current user.
//
// Security:
// - basic:
//
// Responses:
// 200: getUserOrgListResponse
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route GET /user/teams signed_in_user getSignedInUserTeamList
//
// Teams that the actual User is member of.
//
// Return a list of all teams that the current user is member of.
//
// Responses:
// 200: getUserOrgListResponse
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route POST /user/stars/dashboard/{dashboard_id} signed_in_user starDashboard
//
// Star a dashboard.
//
// Stars the given Dashboard for the actual user.
//
// Responses:
// 200: okResponse
// 400: badRequestError
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route DELETE /user/stars/dashboard/{dashboard_id} signed_in_user unstarDashboard
//
// Unstar a dashboard.
//
// Deletes the starring of the given Dashboard for the actual user.
//
// Responses:
// 200: okResponse
// 400: badRequestError
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route PUT /user/password signed_in_user changeUserPassword
//
// Change Password.
//
// Changes the password for the user.
//
// Security:
// - basic:
//
// Responses:
// 200: okResponse
// 400: badRequestError
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route GET /user/quotas signed_in_user getUserQuotas
//
// Fetch user quota.
//
// Responses:
// 200: getQuotaResponse
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:route PUT /user/helpflags/{flag_id} signed_in_user setHelpFlag
//
// Set user help flag.
//
// Responses:
// 200: helpFlagResponse
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route GET /user/helpflags/clear signed_in_user clearHelpFlags
//
// Clear user help flag.
//
// Responses:
// 200: helpFlagResponse
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route GET /user/auth-tokens signed_in_user getSignedInUserAuthTokens
//
// Auth tokens of the actual User.
//
// Return a list of all auth tokens (devices) that the actual user currently have logged in from.
//
// Responses:
// 200: getAuthTokensResponse
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route POST /user/revoke-auth-token signed_in_user revokeSignedINAuthTokenCmd
//
// Revoke an auth token of the actual User.
//
// Revokes the given auth token (device) for the actual user. User of issued auth token (device) will no longer be logged in and will be required to authenticate again upon next activity.
//
// Responses:
// 200: okResponse
// 400: badRequestError
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:parameters starDashboard unstarDashboard
type DashboardIDParam struct {
// in:path
// required:true
DashboardID string `json:"dashboard_id"`
}
// swagger:parameters setHelpFlag
type FlagIDParam struct {
// in:path
// required:true
FlagID string `json:"flag_id"`
}
// swagger:parameters updateUser changeUserPassword
type ChangeUserPasswordParam struct {
// To change the email, name, login, theme, provide another one.
// in:body
// required:true
Body models.ChangeUserPasswordCommand `json:"body"`
}
// swagger:response helpFlagResponse
type HelpFlagResponse struct {
// The response message
// in: body
Body struct {
HelpFlags1 int64 `json:"helpFlags1"`
Message string `json:"message"`
} `json:"body"`
}

View File

@ -0,0 +1,37 @@
package definitions
import "github.com/grafana/grafana/pkg/api/dtos"
// swagger:route GET /user/preferences user_preferences getUserPreferences
//
// Get user preferences.
//
// Responses:
// 200: getPreferencesResponse
// 401: unauthorisedError
// 500: internalServerError
// swagger:route PUT /user/preferences user_preferences updateUserPreferences
//
// Update user preferences.
//
// Omitting a key (`theme`, `homeDashboardId`, `timezone`) will cause the current value to be replaced with the system default value.
//
// Responses:
// 200: okResponse
// 400: badRequestError
// 401: unauthorisedError
// 500: internalServerError
// swagger:parameters updateUserPreferences updateOrgPreferences updateTeamPreferences
type UpdateUserPreferencesParam struct {
// in:body
// required:true
Body dtos.UpdatePrefsCmd `json:"body"`
}
// swagger:response getPreferencesResponse
type GetPreferencesResponse struct {
// in:body
Body dtos.Prefs `json:"body"`
}

View File

@ -0,0 +1,179 @@
package definitions
import (
"github.com/grafana/grafana/pkg/models"
)
// swagger:route GET /users users searchUsers
//
// Get users.
//
// Returns all users that the authenticated user has permission to view, admin permission required.
//
// Responses:
// 200: searchUsersResponse
// 401: unauthorisedError
// 403: forbiddenError
// 500: internalServerError
// swagger:route GET /users/search users searchUsersWithPaging
//
// Get users with paging.
//
// Responses:
// 200: searchUsersResponse
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:route GET /users/{user_id} users getUserByID
//
// Get user by id.
//
// Responses:
// 200: userResponse
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:route GET /users/lookup users getUserByLoginOrEmail
//
// Get user by login or email.
//
// Responses:
// 200: userResponse
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:route PUT /users/{user_id} users updateUser
//
// Update user.
//
// Update the user identified by id.
//
// Responses:
// 200: userResponse
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:route GET /users/{user_id}/orgs users getUserOrgList
//
// Get organizations for user.
//
// Get organizations for user identified by id.
//
// Responses:
// 200: getUserOrgListResponse
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:route GET /users/{user_id}/teams users getUserTeams
//
// Get teams for user.
//
// Get teams for user identified by id.
//
// Responses:
// 200: getUserTeamsResponse
// 401: unauthorisedError
// 403: forbiddenError
// 404: notFoundError
// 500: internalServerError
// swagger:parameters searchUsers
type SearchUsersParams struct {
// Limit the maximum number of users to return per page
// in:query
// required:false
// default:1000
Limit int64 `json:"perpage"`
// Page index for starting fetching users
// in:query
// required:false
// default:1
Page int64 `json:"page"`
}
// swagger:parameters searchUsersWithPaging
type SearchUsersWithPagingParams struct {
// Limit the maximum number of users to return per page
// in:query
// required:false
// default:1000
Limit int64 `json:"perpage"`
// Page index for starting fetching users
// in:query
// required:false
// default:1
Page int64 `json:"page"`
// Query allows return results where the query value is contained in one of the name, login or email fields. Query values with spaces need to be URL encoded e.g. query=Jane%20Doe
// in:query
// required:false
Query string `json:"query"`
}
// swagger:parameters getUserByID updateUser getUserOrgList getUserTeams
// swagger:parameters setPassword setPermissions deleteUser getAuthTokens logoutUser revokeAuthToken
// swagger:parameters syncLDAPUser disableUser enableUser getUserQuota updateUserQuota
// swagger:parameters updateOrgUser deleteOrgUser adminUpdateOrgUser adminDeleteOrgUser
// swagger:parameters updateTeamMember removeTeamMember
// swagger:parameters listUserRoles addUserRole
// swagger:parameters listUserRoles addUserRole removeUserRole setUserRoles listUserRoles
type UserIDParam struct {
// in:path
// required:true
UserID int64 `json:"user_id"`
}
// swagger:parameters getUserByLoginOrEmail
type GetUserByLoginOrEmailParam struct {
// loginOrEmail of the user
// in:query
// required:true
LoginOrEmail string `json:"loginOrEmail"`
}
// swagger:parameters updateUser updateSignedInUser
type UpdateUserParam struct {
// To change the email, name, login, theme, provide another one.
// in:body
// required:true
Body models.UpdateUserCommand `json:"body"`
}
// swagger:response searchUsersResponse
type SearchUsersResponse struct {
// The response message
// in: body
Body models.SearchUserQueryResult `json:"body"`
}
// swagger:response userResponse
type UserResponse struct {
// The response message
// in: body
Body models.UserProfileDTO `json:"body"`
}
// swagger:response getUserOrgListResponse
type GetUserOrgListResponse struct {
// The response message
// in: body
Body []*models.UserOrgDTO `json:"body"`
}
// swagger:response getUserTeamsResponse
type GetUserTeamsResponse struct {
// The response message
// in: body
Body []*models.TeamDTO `json:"body"`
}

View File

@ -0,0 +1,108 @@
package main
import (
"bytes"
_ "embed"
"encoding/json"
"flag"
"fmt"
"io/ioutil"
"os"
"strings"
"github.com/go-openapi/loads"
"github.com/go-openapi/spec"
)
// mergeSpecs merges OSS API spec with one or more other OpenAPI specs
func mergeSpecs(output string, sources ...string) error {
if len(sources) < 2 {
return fmt.Errorf("no APIs to merge")
}
f, err := os.Open(sources[0])
if err != nil {
return err
}
specData, err := ioutil.ReadAll(f)
if err != nil {
return err
}
var specOSS spec.Swagger
if err := json.Unmarshal(specData, &specOSS); err != nil {
return fmt.Errorf("failed to unmarshal original spec: %w", err)
}
for _, s := range sources[1:] {
additionalSpec, err := loads.JSONSpec(s)
if err != nil {
return fmt.Errorf("failed to load spec from: %s: %w", s, err)
}
//TODO: consumes, produces, schemes
//TODO: check for conflicts
for k, d := range additionalSpec.OrigSpec().SwaggerProps.Definitions {
specOSS.SwaggerProps.Definitions[k] = d
}
for k, r := range additionalSpec.OrigSpec().SwaggerProps.Responses {
specOSS.SwaggerProps.Responses[k] = r
}
for k, p := range additionalSpec.OrigSpec().SwaggerProps.Parameters {
specOSS.SwaggerProps.Parameters[k] = p
}
paths := additionalSpec.OrigSpec().SwaggerProps.Paths
if paths != nil {
for k, pi := range paths.Paths {
kk := strings.TrimPrefix(k, specOSS.BasePath) // remove base path if exists
if specOSS.SwaggerProps.Paths == nil {
specOSS.SwaggerProps.Paths = &spec.Paths{
Paths: make(map[string]spec.PathItem),
}
}
specOSS.SwaggerProps.Paths.Paths[kk] = pi
}
}
specOSS.SwaggerProps.Tags = append(specOSS.SwaggerProps.Tags, additionalSpec.OrigSpec().SwaggerProps.Tags...)
}
// write result to file
newSpec, err := specOSS.MarshalJSON()
if err != nil {
return fmt.Errorf("failed to marshal result spec: %w", err)
}
var prettyJSON bytes.Buffer
err = json.Indent(&prettyJSON, newSpec, "", "\t")
if err != nil {
return fmt.Errorf("failed to intend new spec: %w", err)
}
f, err = os.Create(output)
if err != nil {
return fmt.Errorf("failed to create file for new spec: %w", err)
}
_, err = f.Write(prettyJSON.Bytes())
if err != nil {
return fmt.Errorf("failed to write new spec: %w", err)
}
// validate result
return nil
}
func main() {
output := flag.String("o", "../../../swagger-ui/merged.json", "the output path")
flag.Parse()
err := mergeSpecs(*output, flag.Args()...)
if err != nil {
fmt.Printf("something went wrong: %s\n", err.Error())
}
}

84
pkg/api/docs/tags.json Normal file
View File

@ -0,0 +1,84 @@
{
"tags": [
{
"name": "datasources",
"description": "If you are running Grafana Enterprise and have Fine-grained access control enabled, for some endpoints you would need to have relevant permissions. Refer to specific resources to understand what permissions are required."
},
{
"name": "folders",
"description": "Folders are identified by the identifier (id) and the unique identifier (uid).\nThe identifier (id) of a folder is an auto-incrementing numeric value and is only unique per Grafana install.\nThe unique identifier (uid) of a folder can be used for uniquely identify folders between multiple Grafana installs. Its automatically generated if not provided when creating a folder. The uid allows having consistent URLs for accessing folders and when syncing folders between multiple Grafana installs. This means that changing the title of a folder will not break any bookmarked links to that folder.\nThe uid can have a maximum length of 40 characters.\n\nThe General folder (id=0) is special and is not part of the Folder API which means that you cannot use this API for retrieving information about the General folder."
},
{
"name": "folder_permissions",
"description": "Permissions with `folderId=-1` are the default permissions for users with the Viewer and Editor roles. Permissions can be set for a user, a team or a role (Viewer or Editor). Permissions cannot be set for Admins - they always have access to everything."
},
{
"name": "admin",
"description": "The Admin HTTP API does not currently work with an API Token. API Tokens are currently only linked to an organization and an organization role. They cannot be given the permission of server admin, only users can be given that permission. So in order to use these API calls you will have to use Basic Auth and the Grafana user must have the Grafana Admin permission. (The default admin user is called admin and has permission to use this API.)"
},
{
"name": "legacy_alerts",
"description": "You can use the Alerting API to get information about legacy dashboard alerts and their states but this API cannot be used to modify the alert. To create new alerts or modify them you need to update the dashboard JSON that contains the alerts.\nThis topic is relevant for the legacy dashboard alerts only.\nYou can find Grafana 8 alerts API specification details [here](https://editor.swagger.io/?url=https://raw.githubusercontent.com/grafana/grafana/main/pkg/services/ngalert/api/tooling/post.json)."
},
{
"name": "legacy_alerts_notification_channels",
"description": "The identifier (id) of a notification channel is an auto-incrementing numeric value and is only unique per Grafana install.\nThe unique identifier (uid) of a notification channel can be used for uniquely identify a notification channel between multiple Grafana installs. Its automatically generated if not provided when creating a notification channel. The uid allows having consistent URLs for accessing notification channels and when syncing notification channels between multiple Grafana installations, refer to alert notification channel provisioning.\nThe uid can have a maximum length of 40 characters."
},
{
"name": "annotations",
"description": "Grafana Annotations feature released in Grafana 4.6. Annotations are saved in the Grafana database (sqlite, mysql or postgres). Annotations can be global annotations that can be shown on any dashboard by configuring an annotation data source - they are filtered by tags. Or they can be tied to a panel on a dashboard and are then only shown on that panel."
},
{
"name": "library_elements",
"description": "The identifier (ID) of a library element is an auto-incrementing numeric value that is unique per Grafana install.\nThe unique identifier (UID) of a library element uniquely identifies library elements between multiple Grafana installs. Its automatically generated unless you specify it during library element creation. The UID provides consistent URLs for accessing library elements and when syncing library elements between multiple Grafana installs.\nThe maximum length of a UID is 40 characters."
},
{
"name": "orgs",
"description": "The Admin Organizations HTTP API does not currently work with an API Token. API Tokens are currently only linked to an organization and an organization role. They cannot be given the permission of server admin, only users can be given that permission. So in order to use these API calls you will have to use Basic Auth and the Grafana user must have the Grafana Admin permission (The default admin user is called `admin` and has permission to use this API)."
},
{
"name": "current_org_details",
"description": "If you are running Grafana Enterprise and have Fine-grained access control enabled, for some endpoints you would need to have relevant permissions. Refer to specific resources to understand what permissions are required."
},
{
"name": "teams",
"description": "This API can be used to create/update/delete Teams and to add/remove users to Teams. All actions require that the user has the Admin role for the organization."
},
{
"name": "datasource_permissions",
"description": "This API can be used to enable, disable, list, add and remove permissions for a data source.\nPermissions can be set for a user or a team. Permissions cannot be set for Admins - they always have access to everything.\nThis is only available in Grafana Enterprise\nIf you are running Grafana Enterprise and have Fine-grained access control enabled, for some endpoints you would need to have relevant permissions. Refer to specific resources to understand what permissions are required."
},
{
"name": "enterprise",
"description": "These are only available in Grafana Enterprise"
},
{
"name": "access_control",
"description": "The API can be used to create, update, get and list roles, and create or remove built-in role assignments. To use the API, you would need to enable fine-grained access control.\nThis only available in Grafana Enterprise.\nThe API does not currently work with an API Token. So in order to use these API endpoints you will have to use Basic auth."
},
{
"name": "licensing",
"description": "Licensing is only available in Grafana Enterprise. Read more about Grafana Enterprise.\nIf you are running Grafana Enterprise and have Fine-grained access control enabled, for some endpoints you would need to have relevant permissions. Refer to specific resources to understand what permissions are required."
},
{
"name": "reports",
"description": "This API allows you to interact programmatically with the Reporting feature.\nReporting is only available in Grafana Enterprise. Read more about Grafana Enterprise.\nIf you have Fine-grained access Control enabled, for some endpoints you would need to have relevant permissions. Refer to specific resources to understand what permissions are required."
},
{
"name": "alertmanager",
"description": "Grafana Alerting Alertmanager-compatible endpoints"
},
{
"name": "ruler",
"description": "Grafana Alerting endpoints for managing rules"
},
{
"name": "testing",
"description": "Grafana Alerting testing endpoints"
},
{
"name": "prometheus",
"description": "Grafana Alerting Prometheus-compatible endpoints"
}
]
}

View File

@ -2,13 +2,21 @@ package dtos
import "github.com/grafana/grafana/pkg/models"
// swagger:model
type UpdateDashboardAclCommand struct {
Items []DashboardAclUpdateItem `json:"items"`
}
// swagger:model
type DashboardAclUpdateItem struct {
UserID int64 `json:"userId"`
TeamID int64 `json:"teamId"`
Role *models.RoleType `json:"role,omitempty"`
UserID int64 `json:"userId"`
TeamID int64 `json:"teamId"`
Role *models.RoleType `json:"role,omitempty"`
// Permission level
// Description:
// * `1` - View
// * `2` - Edit
// * `4` - Admin
// Enum: 1,2,4
Permission models.PermissionType `json:"permission"`
}

View File

@ -48,11 +48,25 @@ type CurrentUser struct {
type UserPermissionsMap map[string]bool
// swagger:model
type MetricRequest struct {
From string `json:"from"`
To string `json:"to"`
// From Start time in epoch timestamps in milliseconds or relative using Grafana time units.
// required: true
// example: now-1h
From string `json:"from"`
// To End time in epoch timestamps in milliseconds or relative using Grafana time units.
// required: true
// example: now
To string `json:"to"`
// queries.refId Specifies an identifier of the query. Is optional and default to “A”.
// queries.datasourceId Specifies the data source to be queried. Each query in the request must have an unique datasourceId.
// queries.maxDataPoints - Species maximum amount of data points that dashboard panel can render. Is optional and default to 100.
// queries.intervalMs - Specifies the time interval in milliseconds of time series. Is optional and defaults to 1000.
// required: true
// example: [ { "refId": "A", "intervalMs": 86400000, "maxDataPoints": 1092, "datasourceId": 86, "rawSql": "SELECT 1 as valueOne, 2 as valueTwo", "format": "table" } ]
Queries []*simplejson.Json `json:"queries"`
Debug bool `json:"debug"`
// required: false
Debug bool `json:"debug"`
}
func GetGravatarUrl(text string) string {

View File

@ -7,9 +7,14 @@ type Prefs struct {
WeekStart string `json:"weekStart"`
}
// swagger:model
type UpdatePrefsCmd struct {
Theme string `json:"theme"`
HomeDashboardID int64 `json:"homeDashboardId"`
Timezone string `json:"timezone"`
WeekStart string `json:"weekStart"`
// Enum: light,dark
Theme string `json:"theme"`
// The numerical :id of a favorited dashboard
// Default:0
HomeDashboardID int64 `json:"homeDashboardId"`
// Enum: utc,browser
Timezone string `json:"timezone"`
WeekStart string `json:"weekStart"`
}

View File

@ -446,7 +446,7 @@ func (hs *HTTPServer) addMiddlewaresAndStaticRoutes() {
m.Use(middleware.Recovery(hs.Cfg))
hs.mapStatic(m, hs.Cfg.StaticRootPath, "build", "public/build")
hs.mapStatic(m, hs.Cfg.StaticRootPath, "", "public")
hs.mapStatic(m, hs.Cfg.StaticRootPath, "", "public", "/public/views/swagger.html")
hs.mapStatic(m, hs.Cfg.StaticRootPath, "robots.txt", "robots.txt")
if hs.Cfg.ImageUploadProvider == "local" {
@ -553,7 +553,7 @@ func (hs *HTTPServer) apiHealthHandler(ctx *web.Context) {
}
}
func (hs *HTTPServer) mapStatic(m *web.Mux, rootDir string, dir string, prefix string) {
func (hs *HTTPServer) mapStatic(m *web.Mux, rootDir string, dir string, prefix string, exclude ...string) {
headers := func(c *web.Context) {
c.Resp.Header().Set("Cache-Control", "public, max-age=3600")
}
@ -576,6 +576,7 @@ func (hs *HTTPServer) mapStatic(m *web.Mux, rootDir string, dir string, prefix s
SkipLogging: true,
Prefix: prefix,
AddHeaders: headers,
Exclude: exclude,
},
))
}

View File

@ -52,6 +52,8 @@ type StaticOptions struct {
AddHeaders func(ctx *web.Context)
// FileSystem is the interface for supporting any implementation of file system.
FileSystem http.FileSystem
// Exclude paths from being served
Exclude []string
}
// FIXME: to be deleted.
@ -121,6 +123,12 @@ func staticHandler(ctx *web.Context, log log.Logger, opt StaticOptions) bool {
}
file := ctx.Req.URL.Path
for _, p := range opt.Exclude {
if file == p {
return false
}
}
// if we have a prefix, filter requests by stripping the prefix
if opt.Prefix != "" {
if !strings.HasPrefix(file, opt.Prefix) {

7
pkg/api/swagger.go Normal file
View File

@ -0,0 +1,7 @@
package api
import "github.com/grafana/grafana/pkg/models"
func swaggerUI(c *models.ReqContext) {
c.HTML(200, "swagger", nil)
}

View File

@ -55,7 +55,7 @@ type CreateAlertNotificationCommand struct {
OrgId int64 `json:"-"`
EncryptedSecureSettings map[string][]byte `json:"-"`
Result *AlertNotification
Result *AlertNotification `json:"-"`
}
type UpdateAlertNotificationCommand struct {
@ -73,7 +73,7 @@ type UpdateAlertNotificationCommand struct {
OrgId int64 `json:"-"`
EncryptedSecureSettings map[string][]byte `json:"-"`
Result *AlertNotification
Result *AlertNotification `json:"-"`
}
type UpdateAlertNotificationWithUidCommand struct {
@ -88,8 +88,8 @@ type UpdateAlertNotificationWithUidCommand struct {
Settings *simplejson.Json `json:"settings" binding:"Required"`
SecureSettings map[string]string `json:"secureSettings"`
OrgId int64
Result *AlertNotification
OrgId int64 `json:"-"`
Result *AlertNotification `json:"-"`
}
type DeleteAlertNotificationCommand struct {

View File

@ -44,17 +44,32 @@ type DashboardSnapshotDTO struct {
// -----------------
// COMMANDS
// swagger:model
type CreateDashboardSnapshotCommand struct {
// The complete dashboard model.
// required:true
Dashboard *simplejson.Json `json:"dashboard" binding:"Required"`
Name string `json:"name"`
Expires int64 `json:"expires"`
// Snapshot name
// required:false
Name string `json:"name"`
// When the snapshot should expire in seconds in seconds. Default is never to expire.
// required:false
// default:0
Expires int64 `json:"expires"`
// these are passed when storing an external snapshot ref
// Save the snapshot on an external server rather than locally.
// required:false
// default: false
External bool `json:"external"`
ExternalUrl string `json:"-"`
ExternalDeleteUrl string `json:"-"`
Key string `json:"key"`
// Define the unique key. Required if `external` is `true`.
// required:false
Key string `json:"key"`
// Unique key used to delete the snapshot. It is different from the `key` so that only the creator can delete the snapshot. Required if `external` is `true`.
// required:false
DeleteKey string `json:"deleteKey"`
OrgId int64 `json:"-"`

View File

@ -349,13 +349,13 @@ type SaveDashboardCommand struct {
UpdatedAt time.Time
Result *Dashboard
Result *Dashboard `json:"-"`
}
type TrimDashboardCommand struct {
Dashboard *simplejson.Json `json:"dashboard" binding:"Required"`
Meta *simplejson.Json `json:"meta"`
Result *Dashboard
Result *Dashboard `json:"-"`
}
type DashboardProvisioning struct {

View File

@ -92,7 +92,7 @@ type AddDataSourceCommand struct {
ReadOnly bool `json:"-"`
EncryptedSecureJsonData map[string][]byte `json:"-"`
Result *DataSource
Result *DataSource `json:"-"`
}
// Also acts as api DTO
@ -119,7 +119,7 @@ type UpdateDataSourceCommand struct {
ReadOnly bool `json:"-"`
EncryptedSecureJsonData map[string][]byte `json:"-"`
Result *DataSource
Result *DataSource `json:"-"`
}
// DeleteDataSourceCommand will delete a DataSource based on OrgID as well as the UID (preferred), ID, or Name.
@ -171,6 +171,12 @@ type GetDataSourceQuery struct {
// Permissions
// ---------------------
// Datasource permission
// Description:
// * `0` - No Access
// * `1` - Query
// Enum: 0,1
// swagger:model
type DsPermissionType int
const (

View File

@ -62,7 +62,7 @@ type CreateFolderCommand struct {
Uid string `json:"uid"`
Title string `json:"title"`
Result *Folder
Result *Folder `json:"-"`
}
type UpdateFolderCommand struct {
@ -71,7 +71,7 @@ type UpdateFolderCommand struct {
Version int `json:"version"`
Overwrite bool `json:"overwrite"`
Result *Folder
Result *Folder `json:"-"`
}
//

View File

@ -15,6 +15,7 @@ import (
"github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/api"
_ "github.com/grafana/grafana/pkg/api/docs/definitions"
_ "github.com/grafana/grafana/pkg/extensions"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/infra/metrics"

View File

@ -116,6 +116,11 @@ var (
State: FeatureStateAlpha,
RequiresDevMode: true,
},
{
Name: "swaggerUi",
Description: "Serves swagger UI",
State: FeatureStateBeta,
},
{
Name: "featureHighlights",
Description: "Highlight Enterprise features",

View File

@ -87,6 +87,10 @@ const (
// only execute the query saved in a panel
FlagValidatedQueries = "validatedQueries"
// FlagSwaggerUi
// Serves swagger UI
FlagSwaggerUi = "swaggerUi"
// FlagFeatureHighlights
// Highlight Enterprise features
FlagFeatureHighlights = "featureHighlights"

View File

@ -83,7 +83,7 @@ func (l *LibraryElementService) getAllHandler(c *models.ReqContext) response.Res
// patchHandler handles PATCH /api/library-elements/:uid
func (l *LibraryElementService) patchHandler(c *models.ReqContext) response.Response {
cmd := patchLibraryElementCommand{}
cmd := PatchLibraryElementCommand{}
if err := web.Bind(c.Req, &cmd); err != nil {
return response.Error(http.StatusBadRequest, "bad request data", err)
}

View File

@ -436,7 +436,7 @@ func (l *LibraryElementService) handleFolderIDPatches(ctx context.Context, eleme
}
// patchLibraryElement updates a Library Element.
func (l *LibraryElementService) patchLibraryElement(c context.Context, signedInUser *models.SignedInUser, cmd patchLibraryElementCommand, uid string) (LibraryElementDTO, error) {
func (l *LibraryElementService) patchLibraryElement(c context.Context, signedInUser *models.SignedInUser, cmd PatchLibraryElementCommand, uid string) (LibraryElementDTO, error) {
var dto LibraryElementDTO
if err := l.requireSupportedElementKind(cmd.Kind); err != nil {
return LibraryElementDTO{}, err

View File

@ -14,7 +14,7 @@ import (
func TestPatchLibraryElement(t *testing.T) {
scenarioWithPanel(t, "When an admin tries to patch a library panel that does not exist, it should fail",
func(t *testing.T, sc scenarioContext) {
cmd := patchLibraryElementCommand{Kind: int64(models.PanelElement), Version: 1}
cmd := PatchLibraryElementCommand{Kind: int64(models.PanelElement), Version: 1}
sc.ctx.Req = web.SetURLParams(sc.ctx.Req, map[string]string{":uid": "unknown"})
sc.reqContext.Req.Body = mockRequestBody(cmd)
resp := sc.service.patchHandler(sc.reqContext)
@ -24,7 +24,7 @@ func TestPatchLibraryElement(t *testing.T) {
scenarioWithPanel(t, "When an admin tries to patch a library panel that exists, it should succeed",
func(t *testing.T, sc scenarioContext) {
newFolder := createFolderWithACL(t, sc.sqlStore, "NewFolder", sc.user, []folderACLItem{})
cmd := patchLibraryElementCommand{
cmd := PatchLibraryElementCommand{
FolderID: newFolder.Id,
Name: "Panel - New name",
Model: []byte(`
@ -87,7 +87,7 @@ func TestPatchLibraryElement(t *testing.T) {
scenarioWithPanel(t, "When an admin tries to patch a library panel with folder only, it should change folder successfully and return correct result",
func(t *testing.T, sc scenarioContext) {
newFolder := createFolderWithACL(t, sc.sqlStore, "NewFolder", sc.user, []folderACLItem{})
cmd := patchLibraryElementCommand{
cmd := PatchLibraryElementCommand{
FolderID: newFolder.Id,
Kind: int64(models.PanelElement),
Version: 1,
@ -109,7 +109,7 @@ func TestPatchLibraryElement(t *testing.T) {
scenarioWithPanel(t, "When an admin tries to patch a library panel with name only, it should change name successfully and return correct result",
func(t *testing.T, sc scenarioContext) {
cmd := patchLibraryElementCommand{
cmd := PatchLibraryElementCommand{
FolderID: -1,
Name: "New Name",
Kind: int64(models.PanelElement),
@ -132,7 +132,7 @@ func TestPatchLibraryElement(t *testing.T) {
scenarioWithPanel(t, "When an admin tries to patch a library panel with a nonexistent UID, it should change UID successfully and return correct result",
func(t *testing.T, sc scenarioContext) {
cmd := patchLibraryElementCommand{
cmd := PatchLibraryElementCommand{
FolderID: -1,
UID: util.GenerateShortUID(),
Kind: int64(models.PanelElement),
@ -155,7 +155,7 @@ func TestPatchLibraryElement(t *testing.T) {
scenarioWithPanel(t, "When an admin tries to patch a library panel with an invalid UID, it should fail",
func(t *testing.T, sc scenarioContext) {
cmd := patchLibraryElementCommand{
cmd := PatchLibraryElementCommand{
FolderID: -1,
UID: "Testing an invalid UID",
Kind: int64(models.PanelElement),
@ -169,7 +169,7 @@ func TestPatchLibraryElement(t *testing.T) {
scenarioWithPanel(t, "When an admin tries to patch a library panel with an UID that is too long, it should fail",
func(t *testing.T, sc scenarioContext) {
cmd := patchLibraryElementCommand{
cmd := PatchLibraryElementCommand{
FolderID: -1,
UID: "j6T00KRZzj6T00KRZzj6T00KRZzj6T00KRZzj6T00K",
Kind: int64(models.PanelElement),
@ -188,7 +188,7 @@ func TestPatchLibraryElement(t *testing.T) {
sc.reqContext.Req.Body = mockRequestBody(command)
resp := sc.service.createHandler(sc.reqContext)
require.Equal(t, 200, resp.Status())
cmd := patchLibraryElementCommand{
cmd := PatchLibraryElementCommand{
FolderID: -1,
UID: command.UID,
Kind: int64(models.PanelElement),
@ -202,7 +202,7 @@ func TestPatchLibraryElement(t *testing.T) {
scenarioWithPanel(t, "When an admin tries to patch a library panel with model only, it should change model successfully, sync type and description fields and return correct result",
func(t *testing.T, sc scenarioContext) {
cmd := patchLibraryElementCommand{
cmd := PatchLibraryElementCommand{
FolderID: -1,
Model: []byte(`{ "title": "New Model Title", "name": "New Model Name", "type":"graph", "description": "New description" }`),
Kind: int64(models.PanelElement),
@ -231,7 +231,7 @@ func TestPatchLibraryElement(t *testing.T) {
scenarioWithPanel(t, "When an admin tries to patch a library panel with model.description only, it should change model successfully, sync type and description fields and return correct result",
func(t *testing.T, sc scenarioContext) {
cmd := patchLibraryElementCommand{
cmd := PatchLibraryElementCommand{
FolderID: -1,
Model: []byte(`{ "description": "New description" }`),
Kind: int64(models.PanelElement),
@ -258,7 +258,7 @@ func TestPatchLibraryElement(t *testing.T) {
scenarioWithPanel(t, "When an admin tries to patch a library panel with model.type only, it should change model successfully, sync type and description fields and return correct result",
func(t *testing.T, sc scenarioContext) {
cmd := patchLibraryElementCommand{
cmd := PatchLibraryElementCommand{
FolderID: -1,
Model: []byte(`{ "type": "graph" }`),
Kind: int64(models.PanelElement),
@ -285,7 +285,7 @@ func TestPatchLibraryElement(t *testing.T) {
scenarioWithPanel(t, "When another admin tries to patch a library panel, it should change UpdatedBy successfully and return correct result",
func(t *testing.T, sc scenarioContext) {
cmd := patchLibraryElementCommand{FolderID: -1, Version: 1, Kind: int64(models.PanelElement)}
cmd := PatchLibraryElementCommand{FolderID: -1, Version: 1, Kind: int64(models.PanelElement)}
sc.reqContext.UserId = 2
sc.ctx.Req = web.SetURLParams(sc.ctx.Req, map[string]string{":uid": sc.initialResult.Result.UID})
sc.ctx.Req.Body = mockRequestBody(cmd)
@ -307,7 +307,7 @@ func TestPatchLibraryElement(t *testing.T) {
sc.ctx.Req.Body = mockRequestBody(command)
resp := sc.service.createHandler(sc.reqContext)
var result = validateAndUnMarshalResponse(t, resp)
cmd := patchLibraryElementCommand{
cmd := PatchLibraryElementCommand{
Name: "Text - Library Panel",
Version: 1,
Kind: int64(models.PanelElement),
@ -325,7 +325,7 @@ func TestPatchLibraryElement(t *testing.T) {
sc.ctx.Req.Body = mockRequestBody(command)
resp := sc.service.createHandler(sc.reqContext)
var result = validateAndUnMarshalResponse(t, resp)
cmd := patchLibraryElementCommand{
cmd := PatchLibraryElementCommand{
FolderID: 1,
Version: 1,
Kind: int64(models.PanelElement),
@ -338,7 +338,7 @@ func TestPatchLibraryElement(t *testing.T) {
scenarioWithPanel(t, "When an admin tries to patch a library panel in another org, it should fail",
func(t *testing.T, sc scenarioContext) {
cmd := patchLibraryElementCommand{
cmd := PatchLibraryElementCommand{
FolderID: sc.folder.Id,
Version: 1,
Kind: int64(models.PanelElement),
@ -352,7 +352,7 @@ func TestPatchLibraryElement(t *testing.T) {
scenarioWithPanel(t, "When an admin tries to patch a library panel with an old version number, it should fail",
func(t *testing.T, sc scenarioContext) {
cmd := patchLibraryElementCommand{
cmd := PatchLibraryElementCommand{
FolderID: sc.folder.Id,
Version: 1,
Kind: int64(models.PanelElement),
@ -368,7 +368,7 @@ func TestPatchLibraryElement(t *testing.T) {
scenarioWithPanel(t, "When an admin tries to patch a library panel with an other kind, it should succeed but panel should not change",
func(t *testing.T, sc scenarioContext) {
cmd := patchLibraryElementCommand{
cmd := PatchLibraryElementCommand{
FolderID: sc.folder.Id,
Version: 1,
Kind: int64(models.VariableElement),

View File

@ -86,7 +86,7 @@ func TestLibraryElementPermissions(t *testing.T) {
toFolder := createFolderWithACL(t, sc.sqlStore, "Folder", sc.user, testCase.items)
sc.reqContext.SignedInUser.OrgRole = testCase.role
cmd := patchLibraryElementCommand{FolderID: toFolder.Id, Version: 1, Kind: int64(models.PanelElement)}
cmd := PatchLibraryElementCommand{FolderID: toFolder.Id, Version: 1, Kind: int64(models.PanelElement)}
sc.ctx.Req = web.SetURLParams(sc.ctx.Req, map[string]string{":uid": result.Result.UID})
sc.reqContext.Req.Body = mockRequestBody(cmd)
resp = sc.service.patchHandler(sc.reqContext)
@ -103,7 +103,7 @@ func TestLibraryElementPermissions(t *testing.T) {
toFolder := createFolderWithACL(t, sc.sqlStore, "Folder", sc.user, everyonePermissions)
sc.reqContext.SignedInUser.OrgRole = testCase.role
cmd := patchLibraryElementCommand{FolderID: toFolder.Id, Version: 1, Kind: int64(models.PanelElement)}
cmd := PatchLibraryElementCommand{FolderID: toFolder.Id, Version: 1, Kind: int64(models.PanelElement)}
sc.ctx.Req = web.SetURLParams(sc.ctx.Req, map[string]string{":uid": result.Result.UID})
sc.reqContext.Req.Body = mockRequestBody(cmd)
resp = sc.service.patchHandler(sc.reqContext)
@ -154,7 +154,7 @@ func TestLibraryElementPermissions(t *testing.T) {
result := validateAndUnMarshalResponse(t, resp)
sc.reqContext.SignedInUser.OrgRole = testCase.role
cmd := patchLibraryElementCommand{FolderID: 0, Version: 1, Kind: int64(models.PanelElement)}
cmd := PatchLibraryElementCommand{FolderID: 0, Version: 1, Kind: int64(models.PanelElement)}
sc.ctx.Req = web.SetURLParams(sc.ctx.Req, map[string]string{":uid": result.Result.UID})
sc.ctx.Req.Body = mockRequestBody(cmd)
resp = sc.service.patchHandler(sc.reqContext)
@ -170,7 +170,7 @@ func TestLibraryElementPermissions(t *testing.T) {
result := validateAndUnMarshalResponse(t, resp)
sc.reqContext.SignedInUser.OrgRole = testCase.role
cmd := patchLibraryElementCommand{FolderID: folder.Id, Version: 1, Kind: int64(models.PanelElement)}
cmd := PatchLibraryElementCommand{FolderID: folder.Id, Version: 1, Kind: int64(models.PanelElement)}
sc.ctx.Req = web.SetURLParams(sc.ctx.Req, map[string]string{":uid": result.Result.UID})
sc.ctx.Req.Body = mockRequestBody(cmd)
resp = sc.service.patchHandler(sc.reqContext)
@ -219,7 +219,7 @@ func TestLibraryElementPermissions(t *testing.T) {
result := validateAndUnMarshalResponse(t, resp)
sc.reqContext.SignedInUser.OrgRole = testCase.role
cmd := patchLibraryElementCommand{FolderID: -100, Version: 1, Kind: int64(models.PanelElement)}
cmd := PatchLibraryElementCommand{FolderID: -100, Version: 1, Kind: int64(models.PanelElement)}
sc.ctx.Req = web.SetURLParams(sc.ctx.Req, map[string]string{":uid": result.Result.UID})
sc.reqContext.Req.Body = mockRequestBody(cmd)
resp = sc.service.patchHandler(sc.reqContext)

View File

@ -158,22 +158,43 @@ var (
// Commands
// CreateLibraryElementCommand is the command for adding a LibraryElement
// swagger:model
type CreateLibraryElementCommand struct {
FolderID int64 `json:"folderId"`
Name string `json:"name"`
Model json.RawMessage `json:"model"`
Kind int64 `json:"kind" binding:"Required"`
UID string `json:"uid"`
// ID of the folder where the library element is stored.
FolderID int64 `json:"folderId"`
// Name of the library element.
Name string `json:"name"`
// The JSON model for the library element.
// swagger:type object
Model json.RawMessage `json:"model"`
// Kind of element to create, Use 1 for library panels or 2 for c.
// Description:
// * 1 - library panels
// * 2 - library variables
// Enum: 1,2
Kind int64 `json:"kind" binding:"Required"`
// required: false
UID string `json:"uid"`
}
// patchLibraryElementCommand is the command for patching a LibraryElement
type patchLibraryElementCommand struct {
FolderID int64 `json:"folderId" binding:"Default(-1)"`
Name string `json:"name"`
Model json.RawMessage `json:"model,omitempty"`
Kind int64 `json:"kind" binding:"Required"`
Version int64 `json:"version" binding:"Required"`
UID string `json:"uid"`
// PatchLibraryElementCommand is the command for patching a LibraryElement
type PatchLibraryElementCommand struct {
// ID of the folder where the library element is stored.
FolderID int64 `json:"folderId" binding:"Default(-1)"`
// Name of the library element.
Name string `json:"name"`
// The JSON model for the library element.
Model json.RawMessage `json:"model,omitempty"`
// Kind of element to create, Use 1 for library panels or 2 for c.
// Description:
// * 1 - library panels
// * 2 - library variables
// Enum: 1,2
Kind int64 `json:"kind" binding:"Required"`
// Version of the library element you are updating.
Version int64 `json:"version" binding:"Required"`
// required: false
UID string `json:"uid"`
}
// searchLibraryElementsQuery is the query used for searching for Elements

View File

@ -341,6 +341,108 @@
"type": "object",
"x-go-package": "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
},
"CreateDashboardSnapshotCommand": {
"properties": {
"Result": {
"$ref": "#/definitions/DashboardSnapshot"
},
"dashboard": {
"$ref": "#/definitions/Json"
},
"deleteKey": {
"description": "Unique key used to delete the snapshot. It is different from the `key` so that only the creator can delete the snapshot. Required if `external` is `true`.",
"type": "string",
"x-go-name": "DeleteKey"
},
"expires": {
"default": 0,
"description": "When the snapshot should expire in seconds in seconds. Default is never to expire.",
"format": "int64",
"type": "integer",
"x-go-name": "Expires"
},
"external": {
"default": false,
"description": "these are passed when storing an external snapshot ref\nSave the snapshot on an external server rather than locally.",
"type": "boolean",
"x-go-name": "External"
},
"key": {
"description": "Define the unique key. Required if `external` is `true`.",
"type": "string",
"x-go-name": "Key"
},
"name": {
"description": "Snapshot name",
"type": "string",
"x-go-name": "Name"
}
},
"required": [
"dashboard"
],
"type": "object",
"x-go-package": "github.com/grafana/grafana/pkg/models"
},
"DashboardSnapshot": {
"description": "DashboardSnapshot model",
"properties": {
"Created": {
"format": "date-time",
"type": "string"
},
"Dashboard": {
"$ref": "#/definitions/Json"
},
"DashboardEncrypted": {
"items": {
"format": "uint8",
"type": "integer"
},
"type": "array"
},
"DeleteKey": {
"type": "string"
},
"Expires": {
"format": "date-time",
"type": "string"
},
"External": {
"type": "boolean"
},
"ExternalDeleteUrl": {
"type": "string"
},
"ExternalUrl": {
"type": "string"
},
"Id": {
"format": "int64",
"type": "integer"
},
"Key": {
"type": "string"
},
"Name": {
"type": "string"
},
"OrgId": {
"format": "int64",
"type": "integer"
},
"Updated": {
"format": "date-time",
"type": "string"
},
"UserId": {
"format": "int64",
"type": "integer"
}
},
"type": "object",
"x-go-package": "github.com/grafana/grafana/pkg/models"
},
"DateTime": {
"description": "DateTime is a time but it serializes to ISO8601 format with millis\nIt knows how to read 3 different variations of a RFC3339 date time.\nMost APIs we encounter want either millisecond or second precision times.\nThis just tries to make it worry-free.",
"format": "date-time",
@ -382,6 +484,12 @@
"type": "object",
"x-go-package": "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
},
"DsPermissionType": {
"description": "Datasource permission\nDescription:\n`0` - No Access\n`1` - Query\nEnum: 0,1",
"format": "int64",
"type": "integer",
"x-go-package": "github.com/grafana/grafana/pkg/models"
},
"Duration": {
"format": "int64",
"title": "Duration is a type used for marshalling durations.",
@ -2908,7 +3016,6 @@
"x-go-package": "github.com/prometheus/alertmanager/api/v2/models"
},
"alertGroup": {
"description": "AlertGroup alert group",
"properties": {
"alerts": {
"description": "alerts",
@ -2930,7 +3037,9 @@
"labels",
"receiver"
],
"type": "object"
"type": "object",
"x-go-name": "AlertGroup",
"x-go-package": "github.com/prometheus/alertmanager/api/v2/models"
},
"alertGroups": {
"items": {
@ -3183,11 +3292,12 @@
"type": "object"
},
"gettableSilences": {
"description": "GettableSilences gettable silences",
"items": {
"$ref": "#/definitions/gettableSilence"
},
"type": "array"
"type": "array",
"x-go-name": "GettableSilences",
"x-go-package": "github.com/prometheus/alertmanager/api/v2/models"
},
"labelSet": {
"additionalProperties": {

View File

@ -2089,6 +2089,108 @@
},
"x-go-package": "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
},
"CreateDashboardSnapshotCommand": {
"type": "object",
"required": [
"dashboard"
],
"properties": {
"Result": {
"$ref": "#/definitions/DashboardSnapshot"
},
"dashboard": {
"$ref": "#/definitions/Json"
},
"deleteKey": {
"description": "Unique key used to delete the snapshot. It is different from the `key` so that only the creator can delete the snapshot. Required if `external` is `true`.",
"type": "string",
"x-go-name": "DeleteKey"
},
"expires": {
"description": "When the snapshot should expire in seconds in seconds. Default is never to expire.",
"type": "integer",
"format": "int64",
"default": 0,
"x-go-name": "Expires"
},
"external": {
"description": "these are passed when storing an external snapshot ref\nSave the snapshot on an external server rather than locally.",
"type": "boolean",
"default": false,
"x-go-name": "External"
},
"key": {
"description": "Define the unique key. Required if `external` is `true`.",
"type": "string",
"x-go-name": "Key"
},
"name": {
"description": "Snapshot name",
"type": "string",
"x-go-name": "Name"
}
},
"x-go-package": "github.com/grafana/grafana/pkg/models"
},
"DashboardSnapshot": {
"description": "DashboardSnapshot model",
"type": "object",
"properties": {
"Created": {
"type": "string",
"format": "date-time"
},
"Dashboard": {
"$ref": "#/definitions/Json"
},
"DashboardEncrypted": {
"type": "array",
"items": {
"type": "integer",
"format": "uint8"
}
},
"DeleteKey": {
"type": "string"
},
"Expires": {
"type": "string",
"format": "date-time"
},
"External": {
"type": "boolean"
},
"ExternalDeleteUrl": {
"type": "string"
},
"ExternalUrl": {
"type": "string"
},
"Id": {
"type": "integer",
"format": "int64"
},
"Key": {
"type": "string"
},
"Name": {
"type": "string"
},
"OrgId": {
"type": "integer",
"format": "int64"
},
"Updated": {
"type": "string",
"format": "date-time"
},
"UserId": {
"type": "integer",
"format": "int64"
}
},
"x-go-package": "github.com/grafana/grafana/pkg/models"
},
"DateTime": {
"description": "DateTime is a time but it serializes to ISO8601 format with millis\nIt knows how to read 3 different variations of a RFC3339 date time.\nMost APIs we encounter want either millisecond or second precision times.\nThis just tries to make it worry-free.",
"type": "string",
@ -2130,6 +2232,12 @@
},
"x-go-package": "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
},
"DsPermissionType": {
"description": "Datasource permission\nDescription:\n`0` - No Access\n`1` - Query\nEnum: 0,1",
"type": "integer",
"format": "int64",
"x-go-package": "github.com/grafana/grafana/pkg/models"
},
"Duration": {
"type": "integer",
"format": "int64",
@ -4660,7 +4768,6 @@
"x-go-package": "github.com/prometheus/alertmanager/api/v2/models"
},
"alertGroup": {
"description": "AlertGroup alert group",
"type": "object",
"required": [
"alerts",
@ -4683,6 +4790,8 @@
"$ref": "#/definitions/receiver"
}
},
"x-go-name": "AlertGroup",
"x-go-package": "github.com/prometheus/alertmanager/api/v2/models",
"$ref": "#/definitions/alertGroup"
},
"alertGroups": {
@ -4939,11 +5048,12 @@
"$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": {

17498
public/api-merged.json Normal file

File diff suppressed because it is too large Load Diff

13316
public/api-spec.json Normal file

File diff suppressed because it is too large Load Diff

63
public/views/swagger.html Normal file
View File

@ -0,0 +1,63 @@
<!-- HTML for static distribution bundle build -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Swagger UI</title>
<link rel="stylesheet" type="text/css" href="https://unpkg.com/swagger-ui-dist@4.3.0/swagger-ui.css" />
<link rel="icon" type="image/png" href="./favicon-32x32.png" sizes="32x32" />
<link rel="icon" type="image/png" href="./favicon-16x16.png" sizes="16x16" />
<style>
html
{
box-sizing: border-box;
overflow: -moz-scrollbars-vertical;
overflow-y: scroll;
}
*,
*:before,
*:after
{
box-sizing: inherit;
}
body
{
margin:0;
background: #fafafa;
}
</style>
</head>
<body>
<div id="swagger-ui"></div>
<script src="https://unpkg.com/swagger-ui-dist@4.3.0/swagger-ui-bundle.js" charset="UTF-8"> </script>
<script src="https://unpkg.com/swagger-ui-dist@4.3.0/swagger-ui-standalone-preset.js" charset="UTF-8"> </script>
<script>
window.onload = function() {
// Begin Swagger UI call region
const ui = SwaggerUIBundle({
url: "/public/api-merged.json",
dom_id: '#swagger-ui',
deepLinking: true,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
layout: "StandaloneLayout",
filter: true,
tagsSorter: "alpha",
tryItOutEnabled: true
});
// End Swagger UI call region
window.ui = ui;
};
</script>
</body>
</html>