unistore: index search references (#106954)
This commit is contained in:
@@ -103,7 +103,10 @@ type IndexableDocument struct {
|
||||
|
||||
// Maintain a list of resource references.
|
||||
// Someday this will likely be part of https://github.com/grafana/gamma
|
||||
References ResourceReferences `json:"reference,omitempty"`
|
||||
References ResourceReferences `json:"references,omitempty"`
|
||||
|
||||
// internal field for mapping references to kind ( don't set this directly )
|
||||
Reference map[string][]string `json:"reference,omitempty"` // map of kind to list of names
|
||||
|
||||
// When the resource is managed by an upstream repository
|
||||
Manager *utils.ManagerProperties `json:"manager,omitempty"`
|
||||
@@ -121,6 +124,12 @@ func (m *IndexableDocument) UpdateCopyFields() *IndexableDocument {
|
||||
if m.Manager != nil {
|
||||
m.ManagedBy = fmt.Sprintf("%s:%s", m.Manager.Kind, m.Manager.Identity)
|
||||
}
|
||||
|
||||
m.Reference = make(map[string][]string)
|
||||
for _, ref := range m.References {
|
||||
// Group and Version are ignored for now. This could be revisited.
|
||||
m.Reference[ref.Kind] = append(m.Reference[ref.Kind], ref.Name)
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
|
||||
@@ -342,7 +342,6 @@ func (b *bleveIndex) BulkIndex(req *resource.BulkIndexRequest) error {
|
||||
return fmt.Errorf("missing document")
|
||||
}
|
||||
doc := item.Doc.UpdateCopyFields()
|
||||
doc.References = nil // remove references (for now!)
|
||||
|
||||
err := batch.Index(resource.SearchID(doc.Key), doc)
|
||||
if err != nil {
|
||||
|
||||
@@ -137,6 +137,10 @@ func getBleveDocMappings(_ resource.SearchableDocumentFields) *mapping.DocumentM
|
||||
IncludeInAll: false,
|
||||
})
|
||||
|
||||
referenceMapper := bleve.NewDocumentMapping()
|
||||
referenceMapper.DefaultAnalyzer = keyword.Name
|
||||
mapper.AddSubDocumentMapping("reference", referenceMapper)
|
||||
|
||||
labelMapper := bleve.NewDocumentMapping()
|
||||
mapper.AddSubDocumentMapping(resource.SEARCH_FIELD_LABELS, labelMapper)
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
],
|
||||
"schema_version": 38
|
||||
},
|
||||
"reference": [
|
||||
"references": [
|
||||
{
|
||||
"relation": "depends-on",
|
||||
"group": "my-custom-plugin",
|
||||
|
||||
@@ -107,7 +107,7 @@ func runTestSearchBackendTotalDocs(t *testing.T, backend resource.SearchBackend,
|
||||
}
|
||||
|
||||
func runTestResourceIndex(t *testing.T, backend resource.SearchBackend, nsPrefix string) {
|
||||
ctx := testutil.NewTestContext(t, time.Now().Add(5*time.Second))
|
||||
ctx := testutil.NewTestContext(t, time.Now().Add(50*time.Second))
|
||||
ns := resource.NamespacedResource{
|
||||
Namespace: nsPrefix + "-ns1",
|
||||
Group: "group",
|
||||
@@ -236,4 +236,100 @@ func runTestResourceIndex(t *testing.T, backend resource.SearchBackend, nsPrefix
|
||||
require.NotNil(t, resp)
|
||||
require.Equal(t, int64(3), resp.TotalHits) // Both doc1, doc2, and doc3 should have doc now
|
||||
})
|
||||
|
||||
t.Run("Search by LibraryPanel reference", func(t *testing.T) {
|
||||
// Build index with dashboards that have LibraryPanel references
|
||||
index, err := backend.BuildIndex(ctx, ns, 3, 0, nil, func(index resource.ResourceIndex) (int64, error) {
|
||||
err := index.BulkIndex(&resource.BulkIndexRequest{
|
||||
Items: []*resource.BulkIndexItem{
|
||||
{
|
||||
Action: resource.ActionIndex,
|
||||
Doc: &resource.IndexableDocument{
|
||||
Key: &resourcepb.ResourceKey{
|
||||
Namespace: ns.Namespace,
|
||||
Group: ns.Group,
|
||||
Resource: ns.Resource,
|
||||
Name: "dash1",
|
||||
},
|
||||
Title: "Dashboard with Library Panel 1",
|
||||
References: resource.ResourceReferences{
|
||||
{
|
||||
Relation: "depends-on",
|
||||
Group: "dashboards.grafana.app",
|
||||
Kind: "LibraryPanel",
|
||||
Name: "lib-panel-1",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Action: resource.ActionIndex,
|
||||
Doc: &resource.IndexableDocument{
|
||||
Key: &resourcepb.ResourceKey{
|
||||
Namespace: ns.Namespace,
|
||||
Group: ns.Group,
|
||||
Resource: ns.Resource,
|
||||
Name: "dash2",
|
||||
},
|
||||
Title: "Dashboard with Library Panel 2",
|
||||
References: resource.ResourceReferences{
|
||||
{
|
||||
Relation: "depends-on",
|
||||
Group: "dashboards.grafana.app",
|
||||
Kind: "LibraryPanel",
|
||||
Name: "lib-panel-2",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Action: resource.ActionIndex,
|
||||
Doc: &resource.IndexableDocument{
|
||||
Key: &resourcepb.ResourceKey{
|
||||
Namespace: ns.Namespace,
|
||||
Group: ns.Group,
|
||||
Resource: ns.Resource,
|
||||
Name: "dash3",
|
||||
},
|
||||
Title: "Dashboard without Library Panel",
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
return int64(3), nil
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, index)
|
||||
|
||||
// Search for dashboards with specific LibraryPanel reference
|
||||
resp, err := index.Search(ctx, nil, &resourcepb.ResourceSearchRequest{
|
||||
Options: &resourcepb.ListOptions{
|
||||
Key: &resourcepb.ResourceKey{
|
||||
Namespace: ns.Namespace,
|
||||
Group: ns.Group,
|
||||
Resource: ns.Resource,
|
||||
},
|
||||
Fields: []*resourcepb.Requirement{
|
||||
{
|
||||
Key: "reference.LibraryPanel",
|
||||
Operator: "=",
|
||||
Values: []string{"lib-panel-1"},
|
||||
},
|
||||
},
|
||||
},
|
||||
Query: "",
|
||||
Fields: []string{"title"},
|
||||
Limit: 10,
|
||||
}, nil)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, resp)
|
||||
require.Equal(t, int64(1), resp.TotalHits) // Only dash1 should have lib-panel-1
|
||||
|
||||
// Verify the result
|
||||
require.Len(t, resp.Results.Rows, 1)
|
||||
row := resp.Results.Rows[0]
|
||||
require.Equal(t, "dash1", row.Key.Name)
|
||||
require.Equal(t, "Dashboard with Library Panel 1", string(row.Cells[0])) // title field
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user