mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Refactor: Add UID endpoint for get dashboard version (#48600)
* Refactor: Add UID endpoint for get dashboard version * Add initial docs language * Add new endpoint in swagger * Change access control to dashboards * Add parameters to swagger endpoint * Return UID in response; Update docs to reflect this; Implement Ying suggestion * Update docs/sources/http_api/dashboard_versions.md Co-authored-by: Sofia Papagiannaki <1632407+papagian@users.noreply.github.com> * Update pkg/api/api.go Co-authored-by: Sofia Papagiannaki <1632407+papagian@users.noreply.github.com> * Update pkg/models/dashboard_version.go Co-authored-by: Sofia Papagiannaki <1632407+papagian@users.noreply.github.com> * Rename UID to DashboardUID for clarity; use dashUID in method Co-authored-by: Sofia Papagiannaki <1632407+papagian@users.noreply.github.com>
This commit is contained in:
parent
ce6a5694ff
commit
9a0f2ec449
@ -67,6 +67,8 @@ Status Codes:
|
|||||||
|
|
||||||
## Get dashboard version
|
## Get dashboard version
|
||||||
|
|
||||||
|
> **Warning:** This API is deprecated since Grafana v9.0.0 and will be removed in a future release. Refer to the [new get dashboard version API](#get-dashboard-version-by-dashboard-uid).
|
||||||
|
|
||||||
`GET /api/dashboards/id/:dashboardId/versions/:version`
|
`GET /api/dashboards/id/:dashboardId/versions/:version`
|
||||||
|
|
||||||
Get the dashboard version with the given version, for the dashboard with the given id.
|
Get the dashboard version with the given version, for the dashboard with the given id.
|
||||||
@ -177,6 +179,119 @@ Status Codes:
|
|||||||
- **401** - Unauthorized
|
- **401** - Unauthorized
|
||||||
- **404** - Dashboard version not found
|
- **404** - Dashboard version not found
|
||||||
|
|
||||||
|
## Get dashboard version by dashboard UID
|
||||||
|
|
||||||
|
`GET /api/dashboards/uid/:uid/versions/:version`
|
||||||
|
|
||||||
|
Get the dashboard version with the given version, for the dashboard with the given UID.
|
||||||
|
|
||||||
|
**Example request for getting a dashboard version**:
|
||||||
|
|
||||||
|
```http
|
||||||
|
GET /api/dashboards/id/1/versions/1 HTTP/1.1
|
||||||
|
Accept: application/json
|
||||||
|
Content-Type: application/json
|
||||||
|
Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example response**:
|
||||||
|
|
||||||
|
```http
|
||||||
|
HTTP/1.1 200 OK
|
||||||
|
Content-Type: application/json; charset=UTF-8
|
||||||
|
Content-Length: 1300
|
||||||
|
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"dashboardId": 1,
|
||||||
|
"uid": "QA7wKklGz",
|
||||||
|
"parentVersion": 0,
|
||||||
|
"restoredFrom": 0,
|
||||||
|
"version": 1,
|
||||||
|
"created": "2017-04-26T17:18:38-04:00",
|
||||||
|
"message": "Initial save",
|
||||||
|
"data": {
|
||||||
|
"annotations": {
|
||||||
|
"list": [
|
||||||
|
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"editable": true,
|
||||||
|
"gnetId": null,
|
||||||
|
"graphTooltip": 0,
|
||||||
|
"hideControls": false,
|
||||||
|
"id": 1,
|
||||||
|
"links": [
|
||||||
|
|
||||||
|
],
|
||||||
|
"rows": [
|
||||||
|
{
|
||||||
|
"collapse": false,
|
||||||
|
"height": "250px",
|
||||||
|
"panels": [
|
||||||
|
|
||||||
|
],
|
||||||
|
"repeat": null,
|
||||||
|
"repeatIteration": null,
|
||||||
|
"repeatRowId": null,
|
||||||
|
"showTitle": false,
|
||||||
|
"title": "Dashboard Row",
|
||||||
|
"titleSize": "h6"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"schemaVersion": 14,
|
||||||
|
"style": "dark",
|
||||||
|
"tags": [
|
||||||
|
|
||||||
|
],
|
||||||
|
"templating": {
|
||||||
|
"list": [
|
||||||
|
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"time": {
|
||||||
|
"from": "now-6h",
|
||||||
|
"to": "now"
|
||||||
|
},
|
||||||
|
"timepicker": {
|
||||||
|
"refresh_intervals": [
|
||||||
|
"5s",
|
||||||
|
"10s",
|
||||||
|
"30s",
|
||||||
|
"1m",
|
||||||
|
"5m",
|
||||||
|
"15m",
|
||||||
|
"30m",
|
||||||
|
"1h",
|
||||||
|
"2h",
|
||||||
|
"1d"
|
||||||
|
],
|
||||||
|
"time_options": [
|
||||||
|
"5m",
|
||||||
|
"15m",
|
||||||
|
"1h",
|
||||||
|
"6h",
|
||||||
|
"12h",
|
||||||
|
"24h",
|
||||||
|
"2d",
|
||||||
|
"7d",
|
||||||
|
"30d"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"timezone": "browser",
|
||||||
|
"title": "test",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
"createdBy": "admin"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Status Codes:
|
||||||
|
|
||||||
|
- **200** - Ok
|
||||||
|
- **401** - Unauthorized
|
||||||
|
- **404** - Dashboard version not found
|
||||||
|
|
||||||
## Restore dashboard
|
## Restore dashboard
|
||||||
|
|
||||||
`POST /api/dashboards/id/:dashboardId/restore`
|
`POST /api/dashboards/id/:dashboardId/restore`
|
||||||
|
@ -369,6 +369,7 @@ func (hs *HTTPServer) registerRoutes() {
|
|||||||
dashboardRoute.Get("/uid/:uid", authorize(reqSignedIn, ac.EvalPermission(dashboards.ActionDashboardsRead)), routing.Wrap(hs.GetDashboard))
|
dashboardRoute.Get("/uid/:uid", authorize(reqSignedIn, ac.EvalPermission(dashboards.ActionDashboardsRead)), routing.Wrap(hs.GetDashboard))
|
||||||
dashboardRoute.Delete("/uid/:uid", authorize(reqSignedIn, ac.EvalPermission(dashboards.ActionDashboardsDelete)), routing.Wrap(hs.DeleteDashboardByUID))
|
dashboardRoute.Delete("/uid/:uid", authorize(reqSignedIn, ac.EvalPermission(dashboards.ActionDashboardsDelete)), routing.Wrap(hs.DeleteDashboardByUID))
|
||||||
dashboardRoute.Group("/uid/:uid", func(dashUidRoute routing.RouteRegister) {
|
dashboardRoute.Group("/uid/:uid", func(dashUidRoute routing.RouteRegister) {
|
||||||
|
dashUidRoute.Get("/versions/:id", authorize(reqSignedIn, ac.EvalPermission(dashboards.ActionDashboardsWrite)), routing.Wrap(hs.GetDashboardVersion))
|
||||||
dashUidRoute.Group("/permissions", func(dashboardPermissionRoute routing.RouteRegister) {
|
dashUidRoute.Group("/permissions", func(dashboardPermissionRoute routing.RouteRegister) {
|
||||||
dashboardPermissionRoute.Get("/", authorize(reqSignedIn, ac.EvalPermission(dashboards.ActionDashboardsPermissionsRead)), routing.Wrap(hs.GetDashboardPermissionList))
|
dashboardPermissionRoute.Get("/", authorize(reqSignedIn, ac.EvalPermission(dashboards.ActionDashboardsPermissionsRead)), routing.Wrap(hs.GetDashboardPermissionList))
|
||||||
dashboardPermissionRoute.Post("/", authorize(reqSignedIn, ac.EvalPermission(dashboards.ActionDashboardsPermissionsWrite)), routing.Wrap(hs.UpdateDashboardPermissions))
|
dashboardPermissionRoute.Post("/", authorize(reqSignedIn, ac.EvalPermission(dashboards.ActionDashboardsPermissionsWrite)), routing.Wrap(hs.UpdateDashboardPermissions))
|
||||||
|
@ -558,10 +558,26 @@ func (hs *HTTPServer) GetDashboardVersions(c *models.ReqContext) response.Respon
|
|||||||
|
|
||||||
// GetDashboardVersion returns the dashboard version with the given ID.
|
// GetDashboardVersion returns the dashboard version with the given ID.
|
||||||
func (hs *HTTPServer) GetDashboardVersion(c *models.ReqContext) response.Response {
|
func (hs *HTTPServer) GetDashboardVersion(c *models.ReqContext) response.Response {
|
||||||
dashID, err := strconv.ParseInt(web.Params(c.Req)[":dashboardId"], 10, 64)
|
var dashID int64
|
||||||
|
|
||||||
|
var err error
|
||||||
|
dashUID := web.Params(c.Req)[":uid"]
|
||||||
|
|
||||||
|
if dashUID == "" {
|
||||||
|
dashID, err = strconv.ParseInt(web.Params(c.Req)[":dashboardId"], 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return response.Error(http.StatusBadRequest, "dashboardId is invalid", err)
|
return response.Error(http.StatusBadRequest, "dashboardId is invalid", err)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
q := models.GetDashboardQuery{
|
||||||
|
OrgId: c.SignedInUser.OrgId,
|
||||||
|
Uid: dashUID,
|
||||||
|
}
|
||||||
|
if err := hs.SQLStore.GetDashboard(c.Req.Context(), &q); err != nil {
|
||||||
|
return response.Error(http.StatusBadRequest, "failed to get dashboard by UID", err)
|
||||||
|
}
|
||||||
|
dashID = q.Result.Id
|
||||||
|
}
|
||||||
|
|
||||||
guardian := guardian.New(c.Req.Context(), dashID, c.OrgId, c.SignedInUser)
|
guardian := guardian.New(c.Req.Context(), dashID, c.OrgId, c.SignedInUser)
|
||||||
if canSave, err := guardian.CanSave(); err != nil || !canSave {
|
if canSave, err := guardian.CanSave(); err != nil || !canSave {
|
||||||
@ -587,6 +603,7 @@ func (hs *HTTPServer) GetDashboardVersion(c *models.ReqContext) response.Respons
|
|||||||
dashVersionMeta := &models.DashboardVersionMeta{
|
dashVersionMeta := &models.DashboardVersionMeta{
|
||||||
Id: query.Result.Id,
|
Id: query.Result.Id,
|
||||||
DashboardId: query.Result.DashboardId,
|
DashboardId: query.Result.DashboardId,
|
||||||
|
DashboardUID: dashUID,
|
||||||
Data: query.Result.Data,
|
Data: query.Result.Data,
|
||||||
ParentVersion: query.Result.ParentVersion,
|
ParentVersion: query.Result.ParentVersion,
|
||||||
RestoredFrom: query.Result.RestoredFrom,
|
RestoredFrom: query.Result.RestoredFrom,
|
||||||
|
@ -101,7 +101,7 @@ import (
|
|||||||
// 422: unprocessableEntityError
|
// 422: unprocessableEntityError
|
||||||
// 500: internalServerError
|
// 500: internalServerError
|
||||||
|
|
||||||
// swagger:parameters getDashboardByUID deleteDashboardByUID getDashboardPermissionsWithUid postDashboardPermissionsWithUid
|
// swagger:parameters getDashboardByUID deleteDashboardByUID getDashboardPermissionsWithUid postDashboardPermissionsWithUid getDashboardVersionByUID
|
||||||
type UID struct {
|
type UID struct {
|
||||||
// in:path
|
// in:path
|
||||||
// required:true
|
// required:true
|
||||||
|
@ -17,6 +17,21 @@ import "github.com/grafana/grafana/pkg/models"
|
|||||||
//
|
//
|
||||||
// Get a specific dashboard version.
|
// Get a specific dashboard version.
|
||||||
//
|
//
|
||||||
|
// Please refer to [updated API](#/dashboard_versions/getDashboardVersionByUID) instead
|
||||||
|
//
|
||||||
|
// Deprecated: true
|
||||||
|
//
|
||||||
|
// Responses:
|
||||||
|
// 200: dashboardVersionResponse
|
||||||
|
// 401: unauthorisedError
|
||||||
|
// 403: forbiddenError
|
||||||
|
// 404: notFoundError
|
||||||
|
// 500: internalServerError
|
||||||
|
|
||||||
|
// swagger:route GET /dashboards/uid/{uid}/versions/{DashboardVersionID} dashboard_versions getDashboardVersionByUID
|
||||||
|
//
|
||||||
|
// Get a specific dashboard version using UID.
|
||||||
|
//
|
||||||
// Responses:
|
// Responses:
|
||||||
// 200: dashboardVersionResponse
|
// 200: dashboardVersionResponse
|
||||||
// 401: unauthorisedError
|
// 401: unauthorisedError
|
||||||
@ -43,7 +58,7 @@ type DashboardIdParam struct {
|
|||||||
DashboardID int64
|
DashboardID int64
|
||||||
}
|
}
|
||||||
|
|
||||||
// swagger:parameters getDashboardVersion
|
// swagger:parameters getDashboardVersion getDashboardVersionByUID
|
||||||
type DashboardVersionIdParam struct {
|
type DashboardVersionIdParam struct {
|
||||||
// in:path
|
// in:path
|
||||||
DashboardVersionID int64
|
DashboardVersionID int64
|
||||||
|
@ -34,6 +34,7 @@ type DashboardVersion struct {
|
|||||||
type DashboardVersionMeta struct {
|
type DashboardVersionMeta struct {
|
||||||
Id int64 `json:"id"`
|
Id int64 `json:"id"`
|
||||||
DashboardId int64 `json:"dashboardId"`
|
DashboardId int64 `json:"dashboardId"`
|
||||||
|
DashboardUID string `json:"uid"`
|
||||||
ParentVersion int `json:"parentVersion"`
|
ParentVersion int `json:"parentVersion"`
|
||||||
RestoredFrom int `json:"restoredFrom"`
|
RestoredFrom int `json:"restoredFrom"`
|
||||||
Version int `json:"version"`
|
Version int `json:"version"`
|
||||||
|
@ -3715,9 +3715,11 @@
|
|||||||
},
|
},
|
||||||
"/dashboards/id/{DashboardID}/versions/{DashboardVersionID}": {
|
"/dashboards/id/{DashboardID}/versions/{DashboardVersionID}": {
|
||||||
"get": {
|
"get": {
|
||||||
|
"description": "Please refer to [updated API](#/dashboard_versions/getDashboardVersionByUID) instead",
|
||||||
"tags": ["dashboard_versions"],
|
"tags": ["dashboard_versions"],
|
||||||
"summary": "Get a specific dashboard version.",
|
"summary": "Get a specific dashboard version.",
|
||||||
"operationId": "getDashboardVersion",
|
"operationId": "getDashboardVersion",
|
||||||
|
"deprecated": true,
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
@ -3978,6 +3980,46 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/dashboards/uid/{uid}/versions/{DashboardVersionID}": {
|
||||||
|
"get": {
|
||||||
|
"tags": ["dashboard_versions"],
|
||||||
|
"summary": "Get a specific dashboard version using UID.",
|
||||||
|
"operationId": "getDashboardVersionByUID",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"x-go-name": "UID",
|
||||||
|
"name": "uid",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64",
|
||||||
|
"name": "DashboardVersionID",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"$ref": "#/responses/dashboardVersionResponse"
|
||||||
|
},
|
||||||
|
"401": {
|
||||||
|
"$ref": "#/responses/unauthorisedError"
|
||||||
|
},
|
||||||
|
"403": {
|
||||||
|
"$ref": "#/responses/forbiddenError"
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"$ref": "#/responses/notFoundError"
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"$ref": "#/responses/internalServerError"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/datasources": {
|
"/datasources": {
|
||||||
"get": {
|
"get": {
|
||||||
"description": "If you are running Grafana Enterprise and have Fine-grained access control enabled\nyou need to have a permission with action: `datasources:read` and scope: `datasources:*`.",
|
"description": "If you are running Grafana Enterprise and have Fine-grained access control enabled\nyou need to have a permission with action: `datasources:read` and scope: `datasources:*`.",
|
||||||
@ -4692,15 +4734,15 @@
|
|||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"x-go-name": "PermissionID",
|
"x-go-name": "DatasourceID",
|
||||||
"name": "permissionId",
|
"name": "datasource_id",
|
||||||
"in": "path",
|
"in": "path",
|
||||||
"required": true
|
"required": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"x-go-name": "DatasourceID",
|
"x-go-name": "PermissionID",
|
||||||
"name": "datasource_id",
|
"name": "permissionId",
|
||||||
"in": "path",
|
"in": "path",
|
||||||
"required": true
|
"required": true
|
||||||
}
|
}
|
||||||
@ -13670,7 +13712,7 @@
|
|||||||
"x-go-name": "SavedItems"
|
"x-go-name": "SavedItems"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"x-go-package": "github.com/grafana/grafana/pkg/services/preference"
|
"x-go-package": "github.com/grafana/grafana/pkg/models"
|
||||||
},
|
},
|
||||||
"NewApiKeyResult": {
|
"NewApiKeyResult": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@ -14754,7 +14796,7 @@
|
|||||||
"x-go-name": "HomeTab"
|
"x-go-name": "HomeTab"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"x-go-package": "github.com/grafana/grafana/pkg/services/preference"
|
"x-go-package": "github.com/grafana/grafana/pkg/models"
|
||||||
},
|
},
|
||||||
"Receiver": {
|
"Receiver": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
@ -2777,9 +2777,11 @@
|
|||||||
},
|
},
|
||||||
"/dashboards/id/{DashboardID}/versions/{DashboardVersionID}": {
|
"/dashboards/id/{DashboardID}/versions/{DashboardVersionID}": {
|
||||||
"get": {
|
"get": {
|
||||||
|
"description": "Please refer to [updated API](#/dashboard_versions/getDashboardVersionByUID) instead",
|
||||||
"tags": ["dashboard_versions"],
|
"tags": ["dashboard_versions"],
|
||||||
"summary": "Get a specific dashboard version.",
|
"summary": "Get a specific dashboard version.",
|
||||||
"operationId": "getDashboardVersion",
|
"operationId": "getDashboardVersion",
|
||||||
|
"deprecated": true,
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
@ -3040,6 +3042,46 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/dashboards/uid/{uid}/versions/{DashboardVersionID}": {
|
||||||
|
"get": {
|
||||||
|
"tags": ["dashboard_versions"],
|
||||||
|
"summary": "Get a specific dashboard version using UID.",
|
||||||
|
"operationId": "getDashboardVersionByUID",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"x-go-name": "UID",
|
||||||
|
"name": "uid",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64",
|
||||||
|
"name": "DashboardVersionID",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"$ref": "#/responses/dashboardVersionResponse"
|
||||||
|
},
|
||||||
|
"401": {
|
||||||
|
"$ref": "#/responses/unauthorisedError"
|
||||||
|
},
|
||||||
|
"403": {
|
||||||
|
"$ref": "#/responses/forbiddenError"
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"$ref": "#/responses/notFoundError"
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"$ref": "#/responses/internalServerError"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/datasources": {
|
"/datasources": {
|
||||||
"get": {
|
"get": {
|
||||||
"description": "If you are running Grafana Enterprise and have Fine-grained access control enabled\nyou need to have a permission with action: `datasources:read` and scope: `datasources:*`.",
|
"description": "If you are running Grafana Enterprise and have Fine-grained access control enabled\nyou need to have a permission with action: `datasources:read` and scope: `datasources:*`.",
|
||||||
@ -3754,15 +3796,15 @@
|
|||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"x-go-name": "PermissionID",
|
"x-go-name": "DatasourceID",
|
||||||
"name": "permissionId",
|
"name": "datasource_id",
|
||||||
"in": "path",
|
"in": "path",
|
||||||
"required": true
|
"required": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"x-go-name": "DatasourceID",
|
"x-go-name": "PermissionID",
|
||||||
"name": "datasource_id",
|
"name": "permissionId",
|
||||||
"in": "path",
|
"in": "path",
|
||||||
"required": true
|
"required": true
|
||||||
}
|
}
|
||||||
@ -10758,7 +10800,7 @@
|
|||||||
"x-go-name": "SavedItems"
|
"x-go-name": "SavedItems"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"x-go-package": "github.com/grafana/grafana/pkg/services/preference"
|
"x-go-package": "github.com/grafana/grafana/pkg/models"
|
||||||
},
|
},
|
||||||
"NewApiKeyResult": {
|
"NewApiKeyResult": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@ -11211,7 +11253,7 @@
|
|||||||
"x-go-name": "HomeTab"
|
"x-go-name": "HomeTab"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"x-go-package": "github.com/grafana/grafana/pkg/services/preference"
|
"x-go-package": "github.com/grafana/grafana/pkg/models"
|
||||||
},
|
},
|
||||||
"RecordingRuleJSON": {
|
"RecordingRuleJSON": {
|
||||||
"description": "RecordingRuleJSON is the external representation of a recording rule",
|
"description": "RecordingRuleJSON is the external representation of a recording rule",
|
||||||
|
Loading…
Reference in New Issue
Block a user