Search: Include managedBy in DashboardHit result (#111600)
This commit is contained in:
@@ -4,6 +4,7 @@ import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
common "github.com/grafana/grafana/pkg/apimachinery/apis/common/v0alpha1"
|
||||
"github.com/grafana/grafana/pkg/apimachinery/utils"
|
||||
)
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
@@ -69,6 +70,8 @@ type DashboardHit struct {
|
||||
Tags []string `json:"tags,omitempty"`
|
||||
// The k8s name (eg, grafana UID) for the parent folder
|
||||
Folder string `json:"folder,omitempty"`
|
||||
// The resource is managed
|
||||
ManagedBy ManagedBy `json:"managedBy,omitzero,omitempty"`
|
||||
// Stick untyped extra fields in this object (including the sort value)
|
||||
Field *common.Unstructured `json:"field,omitzero,omitempty"`
|
||||
// When using "real" search, this is the score
|
||||
@@ -77,6 +80,15 @@ type DashboardHit struct {
|
||||
Explain *common.Unstructured `json:"explain,omitzero,omitempty"`
|
||||
}
|
||||
|
||||
type ManagedBy struct {
|
||||
Kind utils.ManagerKind `json:"kind"`
|
||||
ID string `json:"id,omitempty"`
|
||||
}
|
||||
|
||||
func (m ManagedBy) IsZero() bool {
|
||||
return m.Kind == "" && m.ID == ""
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
type FacetResult struct {
|
||||
Field string `json:"field,omitempty"`
|
||||
|
||||
@@ -76,6 +76,7 @@ func (in *DashboardHit) DeepCopyInto(out *DashboardHit) {
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
out.ManagedBy = in.ManagedBy
|
||||
if in.Field != nil {
|
||||
in, out := &in.Field, &out.Field
|
||||
*out = (*in).DeepCopy()
|
||||
|
||||
@@ -35,6 +35,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA
|
||||
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v0alpha1.LibraryPanelList": schema_pkg_apis_dashboard_v0alpha1_LibraryPanelList(ref),
|
||||
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v0alpha1.LibraryPanelSpec": schema_pkg_apis_dashboard_v0alpha1_LibraryPanelSpec(ref),
|
||||
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v0alpha1.LibraryPanelStatus": schema_pkg_apis_dashboard_v0alpha1_LibraryPanelStatus(ref),
|
||||
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v0alpha1.ManagedBy": schema_pkg_apis_dashboard_v0alpha1_ManagedBy(ref),
|
||||
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v0alpha1.SearchResults": schema_pkg_apis_dashboard_v0alpha1_SearchResults(ref),
|
||||
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v0alpha1.SortBy": schema_pkg_apis_dashboard_v0alpha1_SortBy(ref),
|
||||
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v0alpha1.SortableField": schema_pkg_apis_dashboard_v0alpha1_SortableField(ref),
|
||||
@@ -337,6 +338,13 @@ func schema_pkg_apis_dashboard_v0alpha1_DashboardHit(ref common.ReferenceCallbac
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"managedBy": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "The resource is managed",
|
||||
Default: map[string]interface{}{},
|
||||
Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v0alpha1.ManagedBy"),
|
||||
},
|
||||
},
|
||||
"field": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Stick untyped extra fields in this object (including the sort value)",
|
||||
@@ -361,7 +369,7 @@ func schema_pkg_apis_dashboard_v0alpha1_DashboardHit(ref common.ReferenceCallbac
|
||||
},
|
||||
},
|
||||
Dependencies: []string{
|
||||
"github.com/grafana/grafana/pkg/apimachinery/apis/common/v0alpha1.Unstructured"},
|
||||
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v0alpha1.ManagedBy", "github.com/grafana/grafana/pkg/apimachinery/apis/common/v0alpha1.Unstructured"},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1027,6 +1035,32 @@ func schema_pkg_apis_dashboard_v0alpha1_LibraryPanelStatus(ref common.ReferenceC
|
||||
}
|
||||
}
|
||||
|
||||
func schema_pkg_apis_dashboard_v0alpha1_ManagedBy(ref common.ReferenceCallback) common.OpenAPIDefinition {
|
||||
return common.OpenAPIDefinition{
|
||||
Schema: spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Type: []string{"object"},
|
||||
Properties: map[string]spec.Schema{
|
||||
"kind": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Default: "",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"id": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
Required: []string{"kind"},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func schema_pkg_apis_dashboard_v0alpha1_SearchResults(ref common.ReferenceCallback) common.OpenAPIDefinition {
|
||||
return common.OpenAPIDefinition{
|
||||
Schema: spec.Schema{
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"maps"
|
||||
"strings"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
@@ -640,6 +641,57 @@ func (b *DashboardsAPIBuilder) GetOpenAPIDefinitions() common.GetOpenAPIDefiniti
|
||||
|
||||
func (b *DashboardsAPIBuilder) PostProcessOpenAPI(oas *spec3.OpenAPI) (*spec3.OpenAPI, error) {
|
||||
oas.Info.Description = "Grafana dashboards as resources"
|
||||
|
||||
// Add dashboard hits manually
|
||||
if oas.Info.Title == "dashboard.grafana.app/v0alpha1" {
|
||||
defs := b.GetOpenAPIDefinitions()(func(path string) spec.Ref { return spec.Ref{} })
|
||||
defsBase := "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v0alpha1."
|
||||
refsBase := "com.github.grafana.grafana.apps.dashboard.pkg.apis.dashboard.v0alpha1."
|
||||
|
||||
kinds := []string{"SearchResults", "DashboardHit", "ManagedBy", "FacetResult", "TermFacet", "SortBy"}
|
||||
|
||||
// Add any missing definitions
|
||||
//-----------------------------
|
||||
for _, k := range kinds {
|
||||
v := defs[defsBase+k]
|
||||
clean := strings.Replace(k, defsBase, refsBase, 1)
|
||||
if oas.Components.Schemas[clean] == nil {
|
||||
switch k {
|
||||
case "SearchResults":
|
||||
v.Schema.Properties["sortBy"] = *spec.RefProperty(
|
||||
"#/components/schemas/SortBy")
|
||||
v.Schema.Properties["hits"] = *spec.ArrayProperty(
|
||||
spec.RefProperty("#/components/schemas/DashboardHit"),
|
||||
)
|
||||
v.Schema.Properties["facets"] = *spec.MapProperty(
|
||||
spec.RefProperty("#/components/schemas/FacetResult"),
|
||||
)
|
||||
case "DashboardHit":
|
||||
v.Schema.Properties["managedBy"] = *spec.RefProperty(
|
||||
"#/components/schemas/ManagedBy")
|
||||
case "FacetResult":
|
||||
v.Schema.Properties["terms"] = *spec.ArrayProperty(
|
||||
spec.RefProperty("#/components/schemas/TermFacet"),
|
||||
)
|
||||
}
|
||||
oas.Components.Schemas[clean] = &v.Schema
|
||||
}
|
||||
}
|
||||
|
||||
p := oas.Paths.Paths["/apis/dashboard.grafana.app/v0alpha1/namespaces/{namespace}/search"]
|
||||
p.Get.Responses.StatusCodeResponses[200] = &spec3.Response{
|
||||
ResponseProps: spec3.ResponseProps{
|
||||
Content: map[string]*spec3.MediaType{
|
||||
"application/json": {
|
||||
MediaTypeProps: spec3.MediaTypeProps{
|
||||
Schema: spec.RefSchema("#/components/schemas/SearchResults"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
return oas, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -291,7 +291,7 @@ func (s *SearchHandler) DoSearch(w http.ResponseWriter, r *http.Request) {
|
||||
Page: int64(page), // for modes 0-2 (legacy)
|
||||
Explain: queryParams.Has("explain") && queryParams.Get("explain") != "false",
|
||||
}
|
||||
fields := []string{"title", "folder", "tags", "description"}
|
||||
fields := []string{"title", "folder", "tags", "description", "manager.kind", "manager.id"}
|
||||
if queryParams.Has("field") {
|
||||
// add fields to search and exclude duplicates
|
||||
for _, f := range queryParams["field"] {
|
||||
|
||||
@@ -213,7 +213,7 @@ func TestSearchHandler(t *testing.T) {
|
||||
if mockClient.LastSearchRequest == nil {
|
||||
t.Fatalf("expected Search to be called, but it was not")
|
||||
}
|
||||
expectedFields := []string{"title", "folder", "tags", "description", "field1", "field2", "field3"}
|
||||
expectedFields := []string{"title", "folder", "tags", "description", "manager.kind", "manager.id", "field1", "field2", "field3"}
|
||||
if fmt.Sprintf("%v", mockClient.LastSearchRequest.Fields) != fmt.Sprintf("%v", expectedFields) {
|
||||
t.Errorf("expected fields %v, got %v", expectedFields, mockClient.LastSearchRequest.Fields)
|
||||
}
|
||||
@@ -242,7 +242,7 @@ func TestSearchHandler(t *testing.T) {
|
||||
if mockClient.LastSearchRequest == nil {
|
||||
t.Fatalf("expected Search to be called, but it was not")
|
||||
}
|
||||
expectedFields := []string{"title", "folder", "tags", "description", "field1"}
|
||||
expectedFields := []string{"title", "folder", "tags", "description", "manager.kind", "manager.id", "field1"}
|
||||
if fmt.Sprintf("%v", mockClient.LastSearchRequest.Fields) != fmt.Sprintf("%v", expectedFields) {
|
||||
t.Errorf("expected fields %v, got %v", expectedFields, mockClient.LastSearchRequest.Fields)
|
||||
}
|
||||
@@ -271,7 +271,7 @@ func TestSearchHandler(t *testing.T) {
|
||||
if mockClient.LastSearchRequest == nil {
|
||||
t.Fatalf("expected Search to be called, but it was not")
|
||||
}
|
||||
expectedFields := []string{"title", "folder", "tags", "description"}
|
||||
expectedFields := []string{"title", "folder", "tags", "description", "manager.kind", "manager.id"}
|
||||
if fmt.Sprintf("%v", mockClient.LastSearchRequest.Fields) != fmt.Sprintf("%v", expectedFields) {
|
||||
t.Errorf("expected fields %v, got %v", expectedFields, mockClient.LastSearchRequest.Fields)
|
||||
}
|
||||
|
||||
@@ -2043,13 +2043,13 @@ func (dr *DashboardServiceImpl) searchProvisionedDashboardsThroughK8s(ctx contex
|
||||
|
||||
dashs := make([]*dashboardProvisioningWithUID, 0)
|
||||
for _, hit := range searchResults.Hits {
|
||||
if utils.ParseManagerKindString(hit.Field.GetNestedString(resource.SEARCH_FIELD_MANAGER_KIND)) != utils.ManagerKindClassicFP { // nolint:staticcheck
|
||||
if utils.ParseManagerKindString(string(hit.ManagedBy.Kind)) != utils.ManagerKindClassicFP { // nolint:staticcheck
|
||||
continue
|
||||
}
|
||||
|
||||
provisioning := &dashboardProvisioningWithUID{
|
||||
DashboardProvisioning: dashboards.DashboardProvisioning{
|
||||
Name: hit.Field.GetNestedString(resource.SEARCH_FIELD_MANAGER_ID),
|
||||
Name: hit.ManagedBy.ID,
|
||||
ExternalID: hit.Field.GetNestedString(resource.SEARCH_FIELD_SOURCE_PATH),
|
||||
CheckSum: hit.Field.GetNestedString(resource.SEARCH_FIELD_SOURCE_CHECKSUM),
|
||||
Updated: hit.Field.GetNestedInt64(resource.SEARCH_FIELD_SOURCE_TIME),
|
||||
|
||||
@@ -5,21 +5,24 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
common "github.com/grafana/grafana/pkg/apimachinery/apis/common/v0alpha1"
|
||||
"github.com/grafana/grafana/pkg/storage/unified/resourcepb"
|
||||
|
||||
"github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v0alpha1"
|
||||
common "github.com/grafana/grafana/pkg/apimachinery/apis/common/v0alpha1"
|
||||
"github.com/grafana/grafana/pkg/apimachinery/utils"
|
||||
"github.com/grafana/grafana/pkg/storage/unified/resource"
|
||||
"github.com/grafana/grafana/pkg/storage/unified/resourcepb"
|
||||
)
|
||||
|
||||
var (
|
||||
excludedFields = map[string]string{
|
||||
resource.SEARCH_FIELD_EXPLAIN: "",
|
||||
resource.SEARCH_FIELD_SCORE: "",
|
||||
resource.SEARCH_FIELD_TITLE: "",
|
||||
resource.SEARCH_FIELD_FOLDER: "",
|
||||
resource.SEARCH_FIELD_TAGS: "",
|
||||
resource.SEARCH_FIELD_DESCRIPTION: "",
|
||||
// These fields exist at the top-level of DashboardHit
|
||||
standardFields = map[string]string{
|
||||
resource.SEARCH_FIELD_EXPLAIN: "",
|
||||
resource.SEARCH_FIELD_SCORE: "",
|
||||
resource.SEARCH_FIELD_TITLE: "",
|
||||
resource.SEARCH_FIELD_FOLDER: "",
|
||||
resource.SEARCH_FIELD_TAGS: "",
|
||||
resource.SEARCH_FIELD_DESCRIPTION: "",
|
||||
resource.SEARCH_FIELD_MANAGER_ID: "",
|
||||
resource.SEARCH_FIELD_MANAGER_KIND: "",
|
||||
}
|
||||
|
||||
IncludeFields = []string{
|
||||
@@ -56,6 +59,8 @@ func ParseResults(result *resourcepb.ResourceSearchResponse, offset int64) (v0al
|
||||
descriptionIDX := -1
|
||||
scoreIDX := -1
|
||||
explainIDX := -1
|
||||
managerKindIDX := -1
|
||||
managerIdIDX := -1
|
||||
|
||||
for i, v := range result.Results.Columns {
|
||||
switch v.Name {
|
||||
@@ -69,6 +74,10 @@ func ParseResults(result *resourcepb.ResourceSearchResponse, offset int64) (v0al
|
||||
folderIDX = i
|
||||
case resource.SEARCH_FIELD_TAGS:
|
||||
tagsIDX = i
|
||||
case resource.SEARCH_FIELD_MANAGER_ID:
|
||||
managerIdIDX = i
|
||||
case resource.SEARCH_FIELD_MANAGER_KIND:
|
||||
managerKindIDX = i
|
||||
case resource.SEARCH_FIELD_DESCRIPTION:
|
||||
descriptionIDX = i
|
||||
}
|
||||
@@ -89,9 +98,10 @@ func ParseResults(result *resourcepb.ResourceSearchResponse, offset int64) (v0al
|
||||
return v0alpha1.SearchResults{}, fmt.Errorf("error parsing Search Response: mismatch number of columns and cells")
|
||||
}
|
||||
|
||||
// Dynamically defined fields
|
||||
fields := &common.Unstructured{}
|
||||
for colIndex, col := range result.Results.Columns {
|
||||
if _, ok := excludedFields[col.Name]; !ok {
|
||||
if _, ok := standardFields[col.Name]; !ok {
|
||||
val, err := resource.DecodeCell(col, colIndex, row.Cells[colIndex])
|
||||
if err != nil {
|
||||
return v0alpha1.SearchResults{}, err
|
||||
@@ -122,6 +132,12 @@ func ParseResults(result *resourcepb.ResourceSearchResponse, offset int64) (v0al
|
||||
if descriptionIDX >= 0 && row.Cells[descriptionIDX] != nil {
|
||||
hit.Description = string(row.Cells[descriptionIDX])
|
||||
}
|
||||
if managerIdIDX >= 0 && row.Cells[managerIdIDX] != nil {
|
||||
hit.ManagedBy.ID = string(row.Cells[managerIdIDX])
|
||||
}
|
||||
if managerKindIDX >= 0 && row.Cells[managerKindIDX] != nil {
|
||||
hit.ManagedBy.Kind = utils.ManagerKind(row.Cells[managerKindIDX])
|
||||
}
|
||||
if tagsIDX >= 0 && row.Cells[tagsIDX] != nil {
|
||||
_ = json.Unmarshal(row.Cells[tagsIDX], &hit.Tags)
|
||||
}
|
||||
|
||||
@@ -276,12 +276,8 @@ func (ss *FolderUnifiedStoreImpl) GetChildren(ctx context.Context, q folder.GetC
|
||||
UID: item.Name,
|
||||
Title: item.Title,
|
||||
ParentUID: item.Folder,
|
||||
ManagedBy: item.ManagedBy.Kind,
|
||||
}
|
||||
|
||||
if item.Field.GetNestedString(resource.SEARCH_FIELD_MANAGER_KIND) != "" {
|
||||
f.ManagedBy = utils.ParseManagerKindString(item.Field.GetNestedString(resource.SEARCH_FIELD_MANAGER_KIND))
|
||||
}
|
||||
|
||||
hits = append(hits, f)
|
||||
}
|
||||
|
||||
|
||||
@@ -1856,59 +1856,7 @@
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"totalHits",
|
||||
"hits"
|
||||
],
|
||||
"properties": {
|
||||
"apiVersion": {
|
||||
"description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
|
||||
"type": "string"
|
||||
},
|
||||
"facets": {
|
||||
"description": "Facet results",
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"default": {}
|
||||
}
|
||||
},
|
||||
"hits": {
|
||||
"description": "The dashboard body (unstructured for now)",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"default": {}
|
||||
}
|
||||
},
|
||||
"kind": {
|
||||
"description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
|
||||
"type": "string"
|
||||
},
|
||||
"maxScore": {
|
||||
"description": "Max score",
|
||||
"type": "number",
|
||||
"format": "double"
|
||||
},
|
||||
"offset": {
|
||||
"description": "Where the query started from",
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"queryCost": {
|
||||
"description": "Cost of running the query",
|
||||
"type": "number",
|
||||
"format": "double"
|
||||
},
|
||||
"sortBy": {
|
||||
"description": "How are the results sorted"
|
||||
},
|
||||
"totalHits": {
|
||||
"description": "The number of matching results",
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"default": 0
|
||||
}
|
||||
}
|
||||
"$ref": "#/components/schemas/SearchResults"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1970,6 +1918,180 @@
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"DashboardHit": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"resource",
|
||||
"name",
|
||||
"title"
|
||||
],
|
||||
"properties": {
|
||||
"description": {
|
||||
"description": "Dashboard description",
|
||||
"type": "string"
|
||||
},
|
||||
"explain": {
|
||||
"description": "Explain the score (if possible)"
|
||||
},
|
||||
"field": {
|
||||
"description": "Stick untyped extra fields in this object (including the sort value)"
|
||||
},
|
||||
"folder": {
|
||||
"description": "The k8s name (eg, grafana UID) for the parent folder",
|
||||
"type": "string"
|
||||
},
|
||||
"managedBy": {
|
||||
"$ref": "#/components/schemas/ManagedBy"
|
||||
},
|
||||
"name": {
|
||||
"description": "The k8s \"name\" (eg, grafana UID)",
|
||||
"type": "string",
|
||||
"default": ""
|
||||
},
|
||||
"resource": {
|
||||
"description": "Dashboard or folder",
|
||||
"type": "string",
|
||||
"default": ""
|
||||
},
|
||||
"score": {
|
||||
"description": "When using \"real\" search, this is the score",
|
||||
"type": "number",
|
||||
"format": "double"
|
||||
},
|
||||
"tags": {
|
||||
"description": "Filter tags",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"default": ""
|
||||
}
|
||||
},
|
||||
"title": {
|
||||
"description": "The display name",
|
||||
"type": "string",
|
||||
"default": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
"FacetResult": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"field": {
|
||||
"type": "string"
|
||||
},
|
||||
"missing": {
|
||||
"description": "The number of documents that do *not* have this field",
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"terms": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/TermFacet"
|
||||
}
|
||||
},
|
||||
"total": {
|
||||
"description": "The distinct terms",
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ManagedBy": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"kind"
|
||||
],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"kind": {
|
||||
"type": "string",
|
||||
"default": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
"SearchResults": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"totalHits",
|
||||
"hits"
|
||||
],
|
||||
"properties": {
|
||||
"apiVersion": {
|
||||
"description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
|
||||
"type": "string"
|
||||
},
|
||||
"facets": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"$ref": "#/components/schemas/FacetResult"
|
||||
}
|
||||
},
|
||||
"hits": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/DashboardHit"
|
||||
}
|
||||
},
|
||||
"kind": {
|
||||
"description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
|
||||
"type": "string"
|
||||
},
|
||||
"maxScore": {
|
||||
"description": "Max score",
|
||||
"type": "number",
|
||||
"format": "double"
|
||||
},
|
||||
"offset": {
|
||||
"description": "Where the query started from",
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"queryCost": {
|
||||
"description": "Cost of running the query",
|
||||
"type": "number",
|
||||
"format": "double"
|
||||
},
|
||||
"sortBy": {
|
||||
"$ref": "#/components/schemas/SortBy"
|
||||
},
|
||||
"totalHits": {
|
||||
"description": "The number of matching results",
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"default": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
"SortBy": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"field"
|
||||
],
|
||||
"properties": {
|
||||
"desc": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"field": {
|
||||
"type": "string",
|
||||
"default": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
"TermFacet": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"count": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"term": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"com.github.grafana.grafana-plugin-sdk-go.experimental.apis.data.v0alpha1.DataQuery": {
|
||||
"description": "Generic query properties",
|
||||
"type": "object",
|
||||
|
||||
@@ -26,28 +26,7 @@ const injectedRtkApi = api
|
||||
overrideExisting: false,
|
||||
});
|
||||
export { injectedRtkApi as generatedAPI };
|
||||
export type GetSearchApiResponse = /** status 200 undefined */ {
|
||||
/** APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources */
|
||||
apiVersion?: string;
|
||||
/** Facet results */
|
||||
facets?: {
|
||||
[key: string]: any;
|
||||
};
|
||||
/** The dashboard body (unstructured for now) */
|
||||
hits: any[];
|
||||
/** Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds */
|
||||
kind?: string;
|
||||
/** Max score */
|
||||
maxScore?: number;
|
||||
/** Where the query started from */
|
||||
offset?: number;
|
||||
/** Cost of running the query */
|
||||
queryCost?: number;
|
||||
/** How are the results sorted */
|
||||
sortBy?: any;
|
||||
/** The number of matching results */
|
||||
totalHits: number;
|
||||
};
|
||||
export type GetSearchApiResponse = /** status 200 undefined */ SearchResults;
|
||||
export type GetSearchApiArg = {
|
||||
/** user query string */
|
||||
query?: string;
|
||||
@@ -66,3 +45,63 @@ export type GetSearchApiArg = {
|
||||
/** add debugging info that may help explain why the result matched */
|
||||
explain?: boolean;
|
||||
};
|
||||
export type TermFacet = {
|
||||
count?: number;
|
||||
term?: string;
|
||||
};
|
||||
export type FacetResult = {
|
||||
field?: string;
|
||||
/** The number of documents that do *not* have this field */
|
||||
missing?: number;
|
||||
terms?: TermFacet[];
|
||||
/** The distinct terms */
|
||||
total?: number;
|
||||
};
|
||||
export type ManagedBy = {
|
||||
id?: string;
|
||||
kind: string;
|
||||
};
|
||||
export type DashboardHit = {
|
||||
/** Dashboard description */
|
||||
description?: string;
|
||||
/** Explain the score (if possible) */
|
||||
explain?: any;
|
||||
/** Stick untyped extra fields in this object (including the sort value) */
|
||||
field?: any;
|
||||
/** The k8s name (eg, grafana UID) for the parent folder */
|
||||
folder?: string;
|
||||
managedBy?: ManagedBy;
|
||||
/** The k8s "name" (eg, grafana UID) */
|
||||
name: string;
|
||||
/** Dashboard or folder */
|
||||
resource: string;
|
||||
/** When using "real" search, this is the score */
|
||||
score?: number;
|
||||
/** Filter tags */
|
||||
tags?: string[];
|
||||
/** The display name */
|
||||
title: string;
|
||||
};
|
||||
export type SortBy = {
|
||||
desc?: boolean;
|
||||
field: string;
|
||||
};
|
||||
export type SearchResults = {
|
||||
/** APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources */
|
||||
apiVersion?: string;
|
||||
facets?: {
|
||||
[key: string]: FacetResult;
|
||||
};
|
||||
hits: DashboardHit[];
|
||||
/** Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds */
|
||||
kind?: string;
|
||||
/** Max score */
|
||||
maxScore?: number;
|
||||
/** Where the query started from */
|
||||
offset?: number;
|
||||
/** Cost of running the query */
|
||||
queryCost?: number;
|
||||
sortBy?: SortBy;
|
||||
/** The number of matching results */
|
||||
totalHits: number;
|
||||
};
|
||||
|
||||
@@ -6,7 +6,7 @@ import { dashboardAPIv0alpha1 } from 'app/api/clients/dashboard/v0alpha1';
|
||||
import { DashboardViewItemWithUIItems, DashboardsTreeItem } from 'app/features/browse-dashboards/types';
|
||||
import { useDispatch, useSelector } from 'app/types/store';
|
||||
|
||||
import { AnnoKeyManagerKind, ManagerKind } from '../../../features/apiserver/types';
|
||||
import { ManagerKind } from '../../../features/apiserver/types';
|
||||
import { PAGE_SIZE } from '../../../features/browse-dashboards/api/services';
|
||||
import { getPaginationPlaceholders } from '../../../features/browse-dashboards/state/utils';
|
||||
|
||||
@@ -138,8 +138,8 @@ export function useFoldersQueryAppPlatform({
|
||||
// query by it.
|
||||
uid: name,
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
||||
managedBy: item.metadata?.annotations?.[AnnoKeyManagerKind] as ManagerKind | undefined,
|
||||
parentUID: item.parentUID,
|
||||
managedBy: item.managedBy?.kind as ManagerKind | undefined,
|
||||
parentUID: item.folder,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user