From e7e77632521f1c0399c8668d3ce6006cc622b015 Mon Sep 17 00:00:00 2001 From: Ryan McKinley Date: Tue, 27 Sep 2022 15:08:47 -0700 Subject: [PATCH] Store/Search: Explore a general interface to extract summary data from a blob (#55598) --- pkg/services/searchV2/bluge.go | 92 +- pkg/services/searchV2/filter.go | 9 +- pkg/services/searchV2/index.go | 24 +- pkg/services/searchV2/index_test.go | 129 +- pkg/services/searchV2/object/dashboard.go | 71 + .../searchV2/object/dashboard_test.go | 112 ++ pkg/services/searchV2/object/table.go | 95 ++ .../object/testdata/dash_labels.jsonc | 693 +++++++++ .../searchV2/object/testdata/dash_raw.jsonc | 459 ++++++ .../object/testdata/dash_references.jsonc | 1239 +++++++++++++++++ .../object/testdata/dash_summary.jsonc | 418 ++++++ .../allowed_actions_scope_all.golden.jsonc | 48 +- .../allowed_actions_scope_uids.golden.jsonc | 48 +- pkg/services/store/object/kind.go | 10 + pkg/services/store/object/object.go | 65 + pkg/services/store/object/reference.go | 51 + pkg/services/store/object/summary.go | 29 + 17 files changed, 3421 insertions(+), 171 deletions(-) create mode 100644 pkg/services/searchV2/object/dashboard.go create mode 100644 pkg/services/searchV2/object/dashboard_test.go create mode 100644 pkg/services/searchV2/object/table.go create mode 100644 pkg/services/searchV2/object/testdata/dash_labels.jsonc create mode 100644 pkg/services/searchV2/object/testdata/dash_raw.jsonc create mode 100644 pkg/services/searchV2/object/testdata/dash_references.jsonc create mode 100644 pkg/services/searchV2/object/testdata/dash_summary.jsonc create mode 100644 pkg/services/store/object/kind.go create mode 100644 pkg/services/store/object/object.go create mode 100644 pkg/services/store/object/reference.go create mode 100644 pkg/services/store/object/summary.go diff --git a/pkg/services/searchV2/bluge.go b/pkg/services/searchV2/bluge.go index e4151a34337..f661af5a321 100644 --- a/pkg/services/searchV2/bluge.go +++ b/pkg/services/searchV2/bluge.go @@ -4,7 +4,6 @@ import ( "context" "encoding/json" "fmt" - "strconv" "strings" "time" @@ -15,6 +14,7 @@ import ( "github.com/grafana/grafana-plugin-sdk-go/data" "github.com/grafana/grafana/pkg/infra/log" + "github.com/grafana/grafana/pkg/services/store/object" ) const ( @@ -94,6 +94,7 @@ func initOrgIndex(dashboards []dashboard, logger log.Logger, extendDoc ExtendDas } folderUID := folderIdLookup[dash.folderID] location := folderUID + doc := getNonFolderDashboardDoc(dash, location) if err := extendDoc(dash.uid, doc); err != nil { return nil, err @@ -138,11 +139,11 @@ func getFolderDashboardDoc(dash dashboard) *bluge.Document { if uid == "" { uid = "general" url = "/dashboards" - dash.info.Title = "General" - dash.info.Description = "" + dash.summary.Name = "General" + dash.summary.Description = "" } - return newSearchDocument(uid, dash.info.Title, dash.info.Description, url). + return newSearchDocument(uid, dash.summary.Name, dash.summary.Description, url). AddField(bluge.NewKeywordField(documentFieldKind, string(entityKindFolder)).Aggregatable().StoreValue()). AddField(bluge.NewDateTimeField(DocumentFieldCreatedAt, dash.created).Sortable().StoreValue()). AddField(bluge.NewDateTimeField(DocumentFieldUpdatedAt, dash.updated).Sortable().StoreValue()) @@ -152,31 +153,34 @@ func getNonFolderDashboardDoc(dash dashboard, location string) *bluge.Document { url := fmt.Sprintf("/d/%s/%s", dash.uid, dash.slug) // Dashboard document - doc := newSearchDocument(dash.uid, dash.info.Title, dash.info.Description, url). + doc := newSearchDocument(dash.uid, dash.summary.Name, dash.summary.Description, url). AddField(bluge.NewKeywordField(documentFieldKind, string(entityKindDashboard)).Aggregatable().StoreValue()). AddField(bluge.NewKeywordField(documentFieldLocation, location).Aggregatable().StoreValue()). AddField(bluge.NewDateTimeField(DocumentFieldCreatedAt, dash.created).Sortable().StoreValue()). AddField(bluge.NewDateTimeField(DocumentFieldUpdatedAt, dash.updated).Sortable().StoreValue()) - for _, tag := range dash.info.Tags { - doc.AddField(bluge.NewKeywordField(documentFieldTag, tag). + // dashboards only use the key part of labels + for k := range dash.summary.Labels { + doc.AddField(bluge.NewKeywordField(documentFieldTag, k). StoreValue(). Aggregatable(). SearchTermPositions()) } - for _, ds := range dash.info.Datasource { - if ds.UID != "" { - doc.AddField(bluge.NewKeywordField(documentFieldDSUID, ds.UID). - StoreValue(). - Aggregatable(). - SearchTermPositions()) - } - if ds.Type != "" { - doc.AddField(bluge.NewKeywordField(documentFieldDSType, ds.Type). - StoreValue(). - Aggregatable(). - SearchTermPositions()) + for _, ref := range dash.summary.References { + if ref.Kind == object.StandardKindDataSource { + if ref.Type != "" { + doc.AddField(bluge.NewKeywordField(documentFieldDSType, ref.Type). + StoreValue(). + Aggregatable(). + SearchTermPositions()) + } + if ref.UID != "" { + doc.AddField(bluge.NewKeywordField(documentFieldDSUID, ref.UID). + StoreValue(). + Aggregatable(). + SearchTermPositions()) + } } } @@ -185,36 +189,38 @@ func getNonFolderDashboardDoc(dash dashboard, location string) *bluge.Document { func getDashboardPanelDocs(dash dashboard, location string) []*bluge.Document { var docs []*bluge.Document - url := fmt.Sprintf("/d/%s/%s", dash.uid, dash.slug) - for _, panel := range dash.info.Panels { - if panel.Type == "row" { + for _, panel := range dash.summary.Nested { + if panel.Kind == "panel-row" { continue // for now, we are excluding rows from the search index } - uid := dash.uid + "#" + strconv.FormatInt(panel.ID, 10) - purl := fmt.Sprintf("%s?viewPanel=%d", url, panel.ID) - - doc := newSearchDocument(uid, panel.Title, panel.Description, purl). - AddField(bluge.NewKeywordField(documentFieldPanelType, panel.Type).Aggregatable().StoreValue()). + doc := newSearchDocument(panel.UID, panel.Name, panel.Description, panel.URL). AddField(bluge.NewKeywordField(documentFieldLocation, location).Aggregatable().StoreValue()). AddField(bluge.NewKeywordField(documentFieldKind, string(entityKindPanel)).Aggregatable().StoreValue()) // likely want independent index for this - for _, xform := range panel.Transformer { - doc.AddField(bluge.NewKeywordField(documentFieldTransformer, xform).Aggregatable()) - } - - for _, ds := range panel.Datasource { - if ds.UID != "" { - doc.AddField(bluge.NewKeywordField(documentFieldDSUID, ds.UID). - StoreValue(). - Aggregatable(). - SearchTermPositions()) - } - if ds.Type != "" { - doc.AddField(bluge.NewKeywordField(documentFieldDSType, ds.Type). - StoreValue(). - Aggregatable(). - SearchTermPositions()) + for _, ref := range dash.summary.References { + switch ref.Kind { + case object.StandardKindDashboard: + if ref.Type != "" { + doc.AddField(bluge.NewKeywordField(documentFieldDSType, ref.Type). + StoreValue(). + Aggregatable(). + SearchTermPositions()) + } + if ref.UID != "" { + doc.AddField(bluge.NewKeywordField(documentFieldDSUID, ref.UID). + StoreValue(). + Aggregatable(). + SearchTermPositions()) + } + case object.StandardKindPanel: + if ref.Type != "" { + doc.AddField(bluge.NewKeywordField(documentFieldPanelType, ref.Type).Aggregatable().StoreValue()) + } + case object.StandardKindTransform: + if ref.Type != "" { + doc.AddField(bluge.NewKeywordField(documentFieldTransformer, ref.Type).Aggregatable()) + } } } diff --git a/pkg/services/searchV2/filter.go b/pkg/services/searchV2/filter.go index 53f4984bed8..bbb1a1b08af 100644 --- a/pkg/services/searchV2/filter.go +++ b/pkg/services/searchV2/filter.go @@ -8,6 +8,7 @@ import ( "github.com/blugelabs/bluge/search/searcher" "github.com/blugelabs/bluge/search/similarity" "github.com/grafana/grafana/pkg/infra/log" + "github.com/grafana/grafana/pkg/services/store/object" ) type PermissionFilter struct { @@ -18,10 +19,10 @@ type PermissionFilter struct { type entityKind string const ( - entityKindPanel entityKind = "panel" - entityKindDashboard entityKind = "dashboard" - entityKindFolder entityKind = "folder" - entityKindDatasource entityKind = "datasource" + entityKindPanel entityKind = object.StandardKindPanel + entityKindDashboard entityKind = object.StandardKindDashboard + entityKindFolder entityKind = object.StandardKindFolder + entityKindDatasource entityKind = object.StandardKindDataSource ) func (r entityKind) IsValid() bool { diff --git a/pkg/services/searchV2/index.go b/pkg/services/searchV2/index.go index 77aa4b80155..06ece251d7d 100644 --- a/pkg/services/searchV2/index.go +++ b/pkg/services/searchV2/index.go @@ -17,9 +17,10 @@ import ( "github.com/grafana/grafana/pkg/infra/tracing" "github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/searchV2/dslookup" - "github.com/grafana/grafana/pkg/services/searchV2/extract" + "github.com/grafana/grafana/pkg/services/searchV2/object" "github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/store" + obj "github.com/grafana/grafana/pkg/services/store/object" "github.com/grafana/grafana/pkg/setting" "go.opentelemetry.io/otel/attribute" @@ -52,7 +53,9 @@ type dashboard struct { slug string created time.Time updated time.Time - info *extract.DashboardInfo + + // Use generic structure + summary *obj.ObjectSummary } // buildSignal is sent when search index is accessed in organization for which @@ -836,9 +839,9 @@ func (l sqlDashboardLoader) LoadDashboards(ctx context.Context, orgID int64, das slug: "", created: time.Now(), updated: time.Now(), - info: &extract.DashboardInfo{ - ID: 0, - Title: "General", + summary: &obj.ObjectSummary{ + //ID: 0, + Name: "General", }, }) } @@ -894,8 +897,15 @@ func (l sqlDashboardLoader) LoadDashboards(ctx context.Context, orgID int64, das readDashboardSpan.SetAttributes("orgID", orgID, attribute.Key("orgID").Int64(orgID)) readDashboardSpan.SetAttributes("dashboardCount", len(rows), attribute.Key("dashboardCount").Int(len(rows))) + reader := object.NewDashboardSummaryBuilder(lookup) + for _, row := range rows { - info, err := extract.ReadDashboard(bytes.NewReader(row.Data), lookup) + obj := &obj.RawObject{ + UID: row.Uid, + Kind: "dashboard", + Body: row.Data, + } + summary, err := reader(obj) if err != nil { l.logger.Warn("Error indexing dashboard data", "error", err, "dashboardId", row.Id, "dashboardSlug", row.Slug) // But append info anyway for now, since we possibly extracted useful information. @@ -908,7 +918,7 @@ func (l sqlDashboardLoader) LoadDashboards(ctx context.Context, orgID int64, das slug: row.Slug, created: row.Created, updated: row.Updated, - info: info, + summary: &summary, }) lastID = row.Id } diff --git a/pkg/services/searchV2/index_test.go b/pkg/services/searchV2/index_test.go index bd1f41a98d3..364a766776c 100644 --- a/pkg/services/searchV2/index_test.go +++ b/pkg/services/searchV2/index_test.go @@ -10,10 +10,10 @@ import ( "github.com/grafana/grafana-plugin-sdk-go/data" "github.com/grafana/grafana/pkg/infra/tracing" "github.com/grafana/grafana/pkg/services/featuremgmt" + "github.com/grafana/grafana/pkg/services/store/object" "github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/infra/log" - "github.com/grafana/grafana/pkg/services/searchV2/extract" "github.com/grafana/grafana/pkg/services/store" "github.com/blugelabs/bluge" @@ -113,15 +113,15 @@ var testDashboards = []dashboard{ { id: 1, uid: "1", - info: &extract.DashboardInfo{ - Title: "test", + summary: &object.ObjectSummary{ + Name: "test", }, }, { id: 2, uid: "2", - info: &extract.DashboardInfo{ - Title: "boom", + summary: &object.ObjectSummary{ + Name: "boom", }, }, } @@ -162,8 +162,8 @@ func TestDashboardIndexUpdates(t *testing.T) { err := index.updateDashboard(context.Background(), testOrgID, orgIdx, dashboard{ id: 3, uid: "3", - info: &extract.DashboardInfo{ - Title: "created", + summary: &object.ObjectSummary{ + Name: "created", }, }) require.NoError(t, err) @@ -181,8 +181,8 @@ func TestDashboardIndexUpdates(t *testing.T) { err := index.updateDashboard(context.Background(), testOrgID, orgIdx, dashboard{ id: 2, uid: "2", - info: &extract.DashboardInfo{ - Title: "nginx", + summary: &object.ObjectSummary{ + Name: "nginx", }, }) require.NoError(t, err) @@ -197,15 +197,15 @@ var testSortDashboards = []dashboard{ { id: 1, uid: "1", - info: &extract.DashboardInfo{ - Title: "a-test", + summary: &object.ObjectSummary{ + Name: "a-test", }, }, { id: 2, uid: "2", - info: &extract.DashboardInfo{ - Title: "z-test", + summary: &object.ObjectSummary{ + Name: "z-test", }, }, } @@ -288,15 +288,15 @@ var testPrefixDashboards = []dashboard{ { id: 1, uid: "1", - info: &extract.DashboardInfo{ - Title: "Archer Data System", + summary: &object.ObjectSummary{ + Name: "Archer Data System", }, }, { id: 2, uid: "2", - info: &extract.DashboardInfo{ - Title: "Document Sync repo", + summary: &object.ObjectSummary{ + Name: "Document Sync repo", }, }, } @@ -366,8 +366,8 @@ var longPrefixDashboards = []dashboard{ { id: 1, uid: "1", - info: &extract.DashboardInfo{ - Title: "Eyjafjallajรถkull Eruption data", + summary: &object.ObjectSummary{ + Name: "Eyjafjallajรถkull Eruption data", }, }, } @@ -385,15 +385,15 @@ var scatteredTokensDashboards = []dashboard{ { id: 1, uid: "1", - info: &extract.DashboardInfo{ - Title: "Three can keep a secret, if two of them are dead (Benjamin Franklin)", + summary: &object.ObjectSummary{ + Name: "Three can keep a secret, if two of them are dead (Benjamin Franklin)", }, }, { id: 3, uid: "2", - info: &extract.DashboardInfo{ - Title: "A secret is powerful when it is empty (Umberto Eco)", + summary: &object.ObjectSummary{ + Name: "A secret is powerful when it is empty (Umberto Eco)", }, }, } @@ -418,25 +418,19 @@ var dashboardsWithFolders = []dashboard{ id: 1, uid: "1", isFolder: true, - info: &extract.DashboardInfo{ - Title: "My folder", + summary: &object.ObjectSummary{ + Name: "My folder", }, }, { id: 2, uid: "2", folderID: 1, - info: &extract.DashboardInfo{ - Title: "Dashboard in folder 1", - Panels: []extract.PanelInfo{ - { - ID: 1, - Title: "Panel 1", - }, - { - ID: 2, - Title: "Panel 2", - }, + summary: &object.ObjectSummary{ + Name: "Dashboard in folder 1", + Nested: []*object.ObjectSummary{ + newNestedPanel(1, "Panel 1"), + newNestedPanel(2, "Panel 2"), }, }, }, @@ -444,26 +438,20 @@ var dashboardsWithFolders = []dashboard{ id: 3, uid: "3", folderID: 1, - info: &extract.DashboardInfo{ - Title: "Dashboard in folder 2", - Panels: []extract.PanelInfo{ - { - ID: 3, - Title: "Panel 3", - }, + summary: &object.ObjectSummary{ + Name: "Dashboard in folder 2", + Nested: []*object.ObjectSummary{ + newNestedPanel(3, "Panel 3"), }, }, }, { id: 4, uid: "4", - info: &extract.DashboardInfo{ - Title: "One more dash", - Panels: []extract.PanelInfo{ - { - ID: 3, - Title: "Panel 4", - }, + summary: &object.ObjectSummary{ + Name: "One more dash", + Nested: []*object.ObjectSummary{ + newNestedPanel(4, "Panel 4"), }, }, }, @@ -517,22 +505,25 @@ var dashboardsWithPanels = []dashboard{ { id: 1, uid: "1", - info: &extract.DashboardInfo{ - Title: "My Dash", - Panels: []extract.PanelInfo{ - { - ID: 1, - Title: "Panel 1", - }, - { - ID: 2, - Title: "Panel 2", - }, + summary: &object.ObjectSummary{ + Name: "My Dash", + Nested: []*object.ObjectSummary{ + newNestedPanel(1, "Panel 1"), + newNestedPanel(2, "Panel 2"), }, }, }, } +func newNestedPanel(id int64, name string) *object.ObjectSummary { + summary := &object.ObjectSummary{ + Kind: "panel", + UID: fmt.Sprintf("???#%d", id), + } + summary.Name = name + return summary +} + func TestDashboardIndex_Panels(t *testing.T) { t.Run("panels-indexed", func(t *testing.T) { index := initTestOrgIndexFromDashes(t, dashboardsWithPanels) @@ -562,15 +553,15 @@ var punctuationSplitNgramDashboards = []dashboard{ { id: 1, uid: "1", - info: &extract.DashboardInfo{ - Title: "heat-torkel", + summary: &object.ObjectSummary{ + Name: "heat-torkel", }, }, { id: 2, uid: "2", - info: &extract.DashboardInfo{ - Title: "topology heatmap", + summary: &object.ObjectSummary{ + Name: "topology heatmap", }, }, } @@ -595,8 +586,8 @@ var camelCaseNgramDashboards = []dashboard{ { id: 1, uid: "1", - info: &extract.DashboardInfo{ - Title: "heatTorkel", + summary: &object.ObjectSummary{ + Name: "heatTorkel", }, }, } @@ -617,8 +608,8 @@ func dashboardsWithTitles(names ...string) []dashboard { out = append(out, dashboard{ id: no, uid: fmt.Sprintf("%d", no), - info: &extract.DashboardInfo{ - Title: name, + summary: &object.ObjectSummary{ + Name: name, }, }) } diff --git a/pkg/services/searchV2/object/dashboard.go b/pkg/services/searchV2/object/dashboard.go new file mode 100644 index 00000000000..fcadd6bb21d --- /dev/null +++ b/pkg/services/searchV2/object/dashboard.go @@ -0,0 +1,71 @@ +package object + +import ( + "bytes" + "fmt" + "strconv" + + "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/services/searchV2/dslookup" + "github.com/grafana/grafana/pkg/services/searchV2/extract" + "github.com/grafana/grafana/pkg/services/store/object" +) + +func NewDashboardSummaryBuilder(lookup dslookup.DatasourceLookup) object.ObjectSummaryBuilder { + return func(obj *object.RawObject) (object.ObjectSummary, error) { + summary := object.ObjectSummary{ + Labels: make(map[string]string), + Fields: make(map[string]interface{}), + } + stream := bytes.NewBuffer(obj.Body) + dash, err := extract.ReadDashboard(stream, lookup) + if err != nil { + summary.Error = &object.ObjectErrorInfo{ + Code: 500, // generic bad error + Message: err.Error(), + } + return summary, err + } + + dashboardRefs := object.NewReferenceAccumulator() + url := fmt.Sprintf("/d/%s/%s", obj.UID, models.SlugifyTitle(dash.Title)) + summary.Name = dash.Title + summary.Description = dash.Description + summary.URL = url + for _, v := range dash.Tags { + summary.Labels[v] = "" + } + if len(dash.TemplateVars) > 0 { + summary.Fields["hasTemplateVars"] = true + } + + for _, panel := range dash.Panels { + panelRefs := object.NewReferenceAccumulator() + p := &object.ObjectSummary{ + UID: obj.UID + "#" + strconv.FormatInt(panel.ID, 10), + Kind: "panel", + } + p.Name = panel.Title + p.Description = panel.Description + p.URL = fmt.Sprintf("%s?viewPanel=%d", url, panel.ID) + p.Fields = make(map[string]interface{}, 0) + + panelRefs.Add("panel", panel.Type, "") + for _, v := range panel.Datasource { + dashboardRefs.Add(object.StandardKindDataSource, v.Type, v.UID) + panelRefs.Add(object.StandardKindDataSource, v.Type, v.UID) + } + + for _, v := range panel.Transformer { + panelRefs.Add(object.StandardKindTransform, v, "") + } + + dashboardRefs.Add(object.StandardKindPanel, panel.Type, "") + p.References = panelRefs.Get() + summary.Nested = append(summary.Nested, p) + } + + summary.References = dashboardRefs.Get() + return summary, nil + } +} diff --git a/pkg/services/searchV2/object/dashboard_test.go b/pkg/services/searchV2/object/dashboard_test.go new file mode 100644 index 00000000000..4c6003557d6 --- /dev/null +++ b/pkg/services/searchV2/object/dashboard_test.go @@ -0,0 +1,112 @@ +package object + +import ( + "bytes" + "crypto/md5" + "encoding/hex" + "encoding/json" + "os" + "path/filepath" + "strings" + "testing" + + "github.com/grafana/grafana-plugin-sdk-go/experimental" + "github.com/grafana/grafana/pkg/services/searchV2/dslookup" + "github.com/grafana/grafana/pkg/services/store/object" + "github.com/stretchr/testify/require" +) + +func dsLookup() dslookup.DatasourceLookup { + return dslookup.CreateDatasourceLookup([]*dslookup.DatasourceQueryResult{ + { + UID: "P8045C56BDA891CB2", + Type: "cloudwatch", + Name: "cloudwatch-name", + IsDefault: false, + }, + { + UID: "default.uid", + Type: "default.type", + Name: "default.name", + IsDefault: true, + }, + }) +} + +func TestReadDashboard(t *testing.T) { + devdash := "../../../../devenv/dev-dashboards/" + + reader := NewDashboardSummaryBuilder(dsLookup()) + failed := make([]string, 0, 10) + table := newSummaryTable() + + snapshots := false + + err := filepath.Walk(devdash, + func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + + if !info.IsDir() && strings.HasSuffix(path, ".json") { + // Ignore gosec warning G304 since it's a test + // nolint:gosec + body, err := os.ReadFile(path) + if err != nil { + return err + } + + obj := &object.RawObject{ + UID: path[len(devdash):], + Size: info.Size(), + Modified: info.ModTime().UnixMilli(), + Body: body, + ETag: createContentsHash(body), + } + + summary, err := reader(obj) + if err != nil { + return err + } + table.Add(obj, summary) + + // Check each snapshot + if snapshots { + out, err := json.MarshalIndent(summary, "", " ") + if err != nil { + return err + } + + gpath := "testdata/gdev-walk-" + strings.ReplaceAll(obj.UID, "/", "-") + + // Ignore gosec warning G304 since it's a test + // nolint:gosec + golden, _ := os.ReadFile(gpath) + + if !bytes.Equal(out, golden) { + failed = append(failed, obj.UID) + err = os.WriteFile(gpath, out, 0600) + if err != nil { + return err + } + } + } + } + return nil + }) + require.NoError(t, err) + + // Check the tabular formts + experimental.CheckGoldenJSONFrame(t, "testdata", "dash_raw", table.Raw, true) + experimental.CheckGoldenJSONFrame(t, "testdata", "dash_summary", table.Summary, true) + experimental.CheckGoldenJSONFrame(t, "testdata", "dash_references", table.References, true) + experimental.CheckGoldenJSONFrame(t, "testdata", "dash_labels", table.Labels, true) + + // accumulated in the walk test + require.Equal(t, []string{}, failed) +} + +func createContentsHash(contents []byte) string { + hash := md5.Sum(contents) + return hex.EncodeToString(hash[:]) +} diff --git a/pkg/services/searchV2/object/table.go b/pkg/services/searchV2/object/table.go new file mode 100644 index 00000000000..37c6a64691b --- /dev/null +++ b/pkg/services/searchV2/object/table.go @@ -0,0 +1,95 @@ +package object + +import ( + "encoding/json" + "sort" + + "github.com/grafana/grafana-plugin-sdk-go/data" + "github.com/grafana/grafana/pkg/services/store/object" +) + +//------------------------------------------------------------------------------ +// Currently this is just for testing. +// In general it will flatten objects + summary into differnet tables +//------------------------------------------------------------------------------ + +type SummaryTable struct { + Raw *data.Frame + Summary *data.Frame + References *data.Frame + Labels *data.Frame +} + +func newSummaryTable() SummaryTable { + return SummaryTable{ + Raw: data.NewFrame("raw", + newField("uid", data.FieldTypeString), + newField("kind", data.FieldTypeString), + newField("size", data.FieldTypeInt64), + newField("etag", data.FieldTypeString), + ), + Summary: data.NewFrame("summary", + newField("uid", data.FieldTypeString), + newField("name", data.FieldTypeString), + newField("fields", data.FieldTypeJSON), + ), + References: data.NewFrame("references", + newField("uid", data.FieldTypeString), + newField("kind", data.FieldTypeString), + newField("type", data.FieldTypeString), + newField("uid", data.FieldTypeString), // yes, same key :grimmice:, path_hash? + ), + Labels: data.NewFrame("labels", + newField("uid", data.FieldTypeString), + newField("key", data.FieldTypeString), + newField("value", data.FieldTypeString), + ), + } +} + +func newField(name string, p data.FieldType) *data.Field { + f := data.NewFieldFromFieldType(p, 0) + f.Name = name + return f +} + +func (x *SummaryTable) Add(obj *object.RawObject, summary object.ObjectSummary) { + x.Raw.AppendRow( + obj.UID, + obj.Kind, + obj.Size, + obj.ETag, + ) + + // Add summary table + fieldsJson, _ := json.Marshal(summary.Fields) + x.Summary.AppendRow( + obj.UID, + summary.Name, + json.RawMessage(fieldsJson), + ) + + // Add references + for _, ref := range summary.References { + x.References.AppendRow( + obj.UID, + ref.Kind, + ref.Type, + ref.UID, + ) + } + + // Stable sort order + keys := make([]string, 0, len(summary.Labels)) + for k := range summary.Labels { + keys = append(keys, k) + } + sort.Strings(keys) + for _, k := range keys { + x.Labels.AppendRow( + obj.UID, + k, + summary.Labels[k], + ) + } +} diff --git a/pkg/services/searchV2/object/testdata/dash_labels.jsonc b/pkg/services/searchV2/object/testdata/dash_labels.jsonc new file mode 100644 index 00000000000..dd1bae4ae22 --- /dev/null +++ b/pkg/services/searchV2/object/testdata/dash_labels.jsonc @@ -0,0 +1,693 @@ +// ๐ŸŒŸ This was machine generated. Do not edit. ๐ŸŒŸ +// +// Frame[0] +// Name: labels +// Dimensions: 3 Fields by 209 Rows +// +-----------------------------------------------------+-----------------+----------------+ +// | Name: uid | Name: key | Name: value | +// | Labels: | Labels: | Labels: | +// | Type: []string | Type: []string | Type: []string | +// +-----------------------------------------------------+-----------------+----------------+ +// | alerting/testdata_alerts.json | alerting | | +// | alerting/testdata_alerts.json | gdev | | +// | all-panels.json | all-panels | | +// | all-panels.json | gdev | | +// | all-panels.json | panel-tests | | +// | datasource-elasticsearch/elasticsearch_compare.json | datasource-test | | +// | datasource-elasticsearch/elasticsearch_compare.json | elasticsearch | | +// | datasource-elasticsearch/elasticsearch_compare.json | gdev | | +// | datasource-elasticsearch/elasticsearch_v7.json | datasource-test | | +// | ... | ... | ... | +// +-----------------------------------------------------+-----------------+----------------+ +// +// +// ๐ŸŒŸ This was machine generated. Do not edit. ๐ŸŒŸ +{ + "frames": [ + { + "schema": { + "name": "labels", + "fields": [ + { + "name": "uid", + "type": "string", + "typeInfo": { + "frame": "string" + } + }, + { + "name": "key", + "type": "string", + "typeInfo": { + "frame": "string" + } + }, + { + "name": "value", + "type": "string", + "typeInfo": { + "frame": "string" + } + } + ] + }, + "data": { + "values": [ + [ + "alerting/testdata_alerts.json", + "alerting/testdata_alerts.json", + "all-panels.json", + "all-panels.json", + "all-panels.json", + "datasource-elasticsearch/elasticsearch_compare.json", + "datasource-elasticsearch/elasticsearch_compare.json", + "datasource-elasticsearch/elasticsearch_compare.json", + "datasource-elasticsearch/elasticsearch_v7.json", + "datasource-elasticsearch/elasticsearch_v7.json", + "datasource-elasticsearch/elasticsearch_v7.json", + "datasource-elasticsearch/elasticsearch_v7_filebeat.json", + "datasource-elasticsearch/elasticsearch_v7_filebeat.json", + "datasource-elasticsearch/elasticsearch_v7_filebeat.json", + "datasource-influxdb/influxdb-logs.json", + "datasource-influxdb/influxdb-logs.json", + "datasource-influxdb/influxdb-logs.json", + "datasource-influxdb/influxdb-templated.json", + "datasource-influxdb/influxdb-templated.json", + "datasource-influxdb/influxdb-templated.json", + "datasource-mssql/mssql_fakedata.json", + "datasource-mssql/mssql_fakedata.json", + "datasource-mssql/mssql_fakedata.json", + "datasource-mssql/mssql_unittest.json", + "datasource-mssql/mssql_unittest.json", + "datasource-mssql/mssql_unittest.json", + "datasource-mysql/mysql_fakedata.json", + "datasource-mysql/mysql_fakedata.json", + "datasource-mysql/mysql_fakedata.json", + "datasource-mysql/mysql_unittest.json", + "datasource-mysql/mysql_unittest.json", + "datasource-mysql/mysql_unittest.json", + "datasource-opentsdb/opentsdb.json", + "datasource-opentsdb/opentsdb.json", + "datasource-opentsdb/opentsdb.json", + "datasource-postgres/postgres_fakedata.json", + "datasource-postgres/postgres_fakedata.json", + "datasource-postgres/postgres_fakedata.json", + "datasource-postgres/postgres_unittest.json", + "datasource-postgres/postgres_unittest.json", + "datasource-postgres/postgres_unittest.json", + "datasource-testdata/bar-gauge-demo2.json", + "datasource-testdata/bar-gauge-demo2.json", + "datasource-testdata/demo1.json", + "datasource-testdata/demo1.json", + "datasource-testdata/new_features_in_v62.json", + "datasource-testdata/new_features_in_v62.json", + "datasource-testdata/new_features_in_v74.json", + "datasource-testdata/new_features_in_v74.json", + "datasource-testdata/new_features_in_v74.json", + "datasource-testdata/new_features_in_v8.json", + "datasource-testdata/new_features_in_v8.json", + "datasource-testdata/new_features_in_v8.json", + "feature-templating/global-variables-and-interpolation.json", + "feature-templating/global-variables-and-interpolation.json", + "feature-templating/templating-dashboard-links-and-variables.json", + "feature-templating/templating-dashboard-links-and-variables.json", + "feature-templating/testdata-datalinks.json", + "feature-templating/testdata-datalinks.json", + "feature-templating/testdata-nested-variables-drilldown.json", + "feature-templating/testdata-nested-variables-drilldown.json", + "feature-templating/testdata-nested-variables.json", + "feature-templating/testdata-nested-variables.json", + "feature-templating/testdata-repeating.json", + "feature-templating/testdata-repeating.json", + "feature-templating/testdata-variables-textbox.json", + "feature-templating/testdata-variables-textbox.json", + "feature-templating/testdata-variables-that-update-on-time-change.json", + "feature-templating/testdata-variables-that-update-on-time-change.json", + "panel-barchart/barchart-autosizing.json", + "panel-barchart/barchart-autosizing.json", + "panel-barchart/barchart-autosizing.json", + "panel-barchart/barchart-autosizing.json", + "panel-bargauge/bar_gauge_demo.json", + "panel-bargauge/bar_gauge_demo.json", + "panel-bargauge/panel_tests_bar_gauge.json", + "panel-bargauge/panel_tests_bar_gauge.json", + "panel-bargauge/panel_tests_bar_gauge2.json", + "panel-bargauge/panel_tests_bar_gauge2.json", + "panel-candlestick/candlestick.json", + "panel-candlestick/candlestick.json", + "panel-candlestick/candlestick.json", + "panel-common/auto_decimals.json", + "panel-common/auto_decimals.json", + "panel-common/color_modes.json", + "panel-common/color_modes.json", + "panel-common/lazy_loading.json", + "panel-common/lazy_loading.json", + "panel-common/linked-viz.json", + "panel-common/panels_without_title.json", + "panel-common/panels_without_title.json", + "panel-common/shared_queries.json", + "panel-common/shared_queries.json", + "panel-gauge/gauge-multi-series.json", + "panel-gauge/gauge-multi-series.json", + "panel-gauge/gauge-multi-series.json", + "panel-gauge/gauge_tests.json", + "panel-gauge/gauge_tests.json", + "panel-geomap/geomap-9.1.json", + "panel-geomap/geomap-9.1.json", + "panel-geomap/geomap-9.1.json", + "panel-geomap/geomap-color-field.json", + "panel-geomap/geomap-color-field.json", + "panel-geomap/geomap-color-field.json", + "panel-geomap/geomap-spatial-operations-transformer.json", + "panel-geomap/geomap-spatial-operations-transformer.json", + "panel-geomap/geomap-spatial-operations-transformer.json", + "panel-geomap/geomap_multi-layers.json", + "panel-geomap/geomap_multi-layers.json", + "panel-geomap/geomap_multi-layers.json", + "panel-geomap/panel-geomap.json", + "panel-geomap/panel-geomap.json", + "panel-geomap/panel-geomap.json", + "panel-graph/graph-gradient-area-fills.json", + "panel-graph/graph-gradient-area-fills.json", + "panel-graph/graph-gradient-area-fills.json", + "panel-graph/graph-ng-by-value-color-schemes.json", + "panel-graph/graph-ng-by-value-color-schemes.json", + "panel-graph/graph-ng-by-value-color-schemes.json", + "panel-graph/graph-ng-gradient-area.json", + "panel-graph/graph-ng-gradient-area.json", + "panel-graph/graph-ng-gradient-area.json", + "panel-graph/graph-ng-hue-gradients.json", + "panel-graph/graph-ng-hue-gradients.json", + "panel-graph/graph-ng-hue-gradients.json", + "panel-graph/graph-ng-nulls.json", + "panel-graph/graph-ng-nulls.json", + "panel-graph/graph-ng-nulls.json", + "panel-graph/graph-ng-soft-limits.json", + "panel-graph/graph-ng-soft-limits.json", + "panel-graph/graph-ng-soft-limits.json", + "panel-graph/graph-ng-stacking.json", + "panel-graph/graph-ng-stacking.json", + "panel-graph/graph-ng-stacking.json", + "panel-graph/graph-ng-stacking2.json", + "panel-graph/graph-ng-stacking2.json", + "panel-graph/graph-ng-stacking2.json", + "panel-graph/graph-ng-thresholds.json", + "panel-graph/graph-ng-thresholds.json", + "panel-graph/graph-ng-thresholds.json", + "panel-graph/graph-ng-time.json", + "panel-graph/graph-ng-time.json", + "panel-graph/graph-ng-time.json", + "panel-graph/graph-ng-y-ticks-zero-decimals.json", + "panel-graph/graph-ng-y-ticks-zero-decimals.json", + "panel-graph/graph-ng-y-ticks-zero-decimals.json", + "panel-graph/graph-ng-yaxis-ticks.json", + "panel-graph/graph-ng-yaxis-ticks.json", + "panel-graph/graph-ng-yaxis-ticks.json", + "panel-graph/graph-ng.json", + "panel-graph/graph-ng.json", + "panel-graph/graph-ng.json", + "panel-graph/graph-shared-tooltip-cursor-position.json", + "panel-graph/graph-shared-tooltip-cursor-position.json", + "panel-graph/graph-shared-tooltip-cursor-position.json", + "panel-graph/graph-shared-tooltips.json", + "panel-graph/graph-shared-tooltips.json", + "panel-graph/graph-shared-tooltips.json", + "panel-graph/graph-time-regions.json", + "panel-graph/graph-time-regions.json", + "panel-graph/graph-time-regions.json", + "panel-graph/graph_tests.json", + "panel-graph/graph_tests.json", + "panel-graph/graph_tests.json", + "panel-graph/graph_y_axis.json", + "panel-graph/graph_y_axis.json", + "panel-heatmap/heatmap-calculate-log.json", + "panel-heatmap/heatmap-calculate-log.json", + "panel-heatmap/heatmap-calculate-log.json", + "panel-heatmap/heatmap-legacy.json", + "panel-heatmap/heatmap-legacy.json", + "panel-heatmap/heatmap-legacy.json", + "panel-histogram/histogram_tests.json", + "panel-histogram/histogram_tests.json", + "panel-histogram/histogram_tests.json", + "panel-piechart/panel_test_piechart.json", + "panel-piechart/panel_test_piechart.json", + "panel-polystat/polystat_test.json", + "panel-polystat/polystat_test.json", + "panel-polystat/polystat_test.json", + "panel-stat/panel-stat-tests.json", + "panel-stat/panel-stat-tests.json", + "panel-stat/panel-stat-tests.json", + "panel-table/table_pagination.json", + "panel-table/table_pagination.json", + "panel-table/table_tests.json", + "panel-table/table_tests.json", + "panel-table/table_tests_new.json", + "panel-table/table_tests_new.json", + "panel-timeline/timeline-demo.json", + "panel-timeline/timeline-demo.json", + "panel-timeline/timeline-demo.json", + "panel-timeline/timeline-demo.json", + "panel-timeline/timeline-modes.json", + "panel-timeline/timeline-modes.json", + "panel-timeline/timeline-modes.json", + "scenarios/time_zone_support.json", + "scenarios/time_zone_support.json", + "scenarios/time_zone_support.json", + "scenarios/time_zone_support.json", + "transforms/config-from-query.json", + "transforms/config-from-query.json", + "transforms/join-by-field.json", + "transforms/join-by-field.json", + "transforms/join-by-labels.json", + "transforms/join-by-labels.json", + "transforms/reuse.json", + "transforms/rows-to-fields.json", + "transforms/rows-to-fields.json" + ], + [ + "alerting", + "gdev", + "all-panels", + "gdev", + "panel-tests", + "datasource-test", + "elasticsearch", + "gdev", + "datasource-test", + "elasticsearch", + "gdev", + "datasource-test", + "elasticsearch", + "gdev", + "datasource-test", + "gdev", + "influxdb", + "datasource-test", + "gdev", + "influxdb", + "datasource-test", + "gdev", + "mssql", + "datasource-test", + "gdev", + "mssql", + "datasource-tags", + "gdev", + "mysql", + "datasource-test", + "gdev", + "mysql", + "datasource-test", + "gdev", + "opentsdb", + "datasource-test", + "gdev", + "postgres", + "datasource-test", + "gdev", + "postgres", + "demo", + "gdev", + "demo", + "gdev", + "demo", + "gdev", + "demo", + "gdev", + "graph-ng", + "demo", + "gdev", + "graph-ng", + "gdev", + "templating", + "gdev", + "templating", + "gdev", + "templating", + "gdev", + "templating", + "gdev", + "templating", + "gdev", + "templating", + "gdev", + "templating", + "gdev", + "templating", + "barchart", + "gdev", + "graph-ng", + "panel-tests", + "demo", + "gdev", + "gdev", + "panel-tests", + "gdev", + "panel-tests", + "gdev", + "graph-ng", + "panel-tests", + "gdev", + "panel-tests", + "demo", + "gdev", + "demo", + "gdev", + "gdev", + "gdev", + "panel-tests", + "datasource-test", + "gdev", + "gauge", + "gdev", + "panel-tests", + "gdev", + "panel-tests", + "gdev", + "geomap", + "panel-tests", + "gdev", + "geomap", + "panel-tests", + "gdev", + "geomap", + "panel-tests", + "gdev", + "geomap", + "panel-tests", + "gdev", + "geomap", + "panel-tests", + "gdev", + "graph", + "panel-tests", + "gdev", + "graph-ng", + "panel-tests", + "gdev", + "graph-ng", + "panel-tests", + "gdev", + "graph-ng", + "panel-tests", + "gdev", + "graph-ng", + "panel-tests", + "gdev", + "graph-ng", + "panel-tests", + "gdev", + "graph-ng", + "panel-tests", + "gdev", + "graph-ng", + "panel-tests", + "gdev", + "graph-ng", + "panel-tests", + "gdev", + "graph-ng", + "panel-tests", + "gdev", + "graph-ng", + "panel-tests", + "gdev", + "graph-ng", + "panel-tests", + "gdev", + "graph-ng", + "panel-tests", + "gdev", + "graph-ng", + "panel-tests", + "gdev", + "graph-ng", + "panel-tests", + "gdev", + "graph", + "panel-tests", + "gdev", + "graph", + "panel-tests", + "gdev", + "panel-tests", + "gdev", + "graph-ng", + "panel-tests", + "gdev", + "graph-ng", + "panel-tests", + "gdev", + "graph-ng", + "panel-tests", + "gdev", + "panel-tests", + "gdev", + "panel-test", + "polystat", + "gdev", + "graph-ng", + "panel-tests", + "gdev", + "panel-tests", + "gdev", + "panel-tests", + "gdev", + "panel-tests", + "demo", + "gdev", + "graph-ng", + "panel-tests", + "gdev", + "graph-ng", + "panel-tests", + "gdev", + "graph", + "panel-tests", + "table", + "gdev", + "transform", + "gdev", + "transform", + "gdev", + "transform", + "devenv", + "gdev", + "transform" + ], + [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ] + ] + } + } + ] +} \ No newline at end of file diff --git a/pkg/services/searchV2/object/testdata/dash_raw.jsonc b/pkg/services/searchV2/object/testdata/dash_raw.jsonc new file mode 100644 index 00000000000..3223a3f73c6 --- /dev/null +++ b/pkg/services/searchV2/object/testdata/dash_raw.jsonc @@ -0,0 +1,459 @@ +// ๐ŸŒŸ This was machine generated. Do not edit. ๐ŸŒŸ +// +// Frame[0] +// Name: raw +// Dimensions: 4 Fields by 96 Rows +// +---------------------------------------------------------+----------------+---------------+----------------------------------+ +// | Name: uid | Name: kind | Name: size | Name: etag | +// | Labels: | Labels: | Labels: | Labels: | +// | Type: []string | Type: []string | Type: []int64 | Type: []string | +// +---------------------------------------------------------+----------------+---------------+----------------------------------+ +// | alerting/testdata_alerts.json | | 16402 | a3679c3611fc3a83b0a9418e8f4cd0eb | +// | all-panels.json | | 23018 | a52c6dab16ecc2d3fd0b1e1edad930d6 | +// | datasource-elasticsearch/elasticsearch_compare.json | | 284527 | 394573393efa229fb0b8a3630e177c6d | +// | datasource-elasticsearch/elasticsearch_v7.json | | 16554 | 68b3570b21e53cec3d3514ba222948a3 | +// | datasource-elasticsearch/elasticsearch_v7_filebeat.json | | 5411 | e9c22bae37ecf4e8c031a6fd39f8bfe5 | +// | datasource-influxdb/influxdb-logs.json | | 4052 | 65b5cc531e621170e6a1a8ed4b04a7ca | +// | datasource-influxdb/influxdb-templated.json | | 7571 | 3aedc5a23691a50adff0d7d8e2d8ed43 | +// | datasource-mssql/mssql_fakedata.json | | 13821 | 38d1fe0cecdbfc4c0e733f88250c74f7 | +// | datasource-mssql/mssql_unittest.json | | 67893 | 7d2f553e07ef2a0b06201fb93ed22753 | +// | ... | ... | ... | ... | +// +---------------------------------------------------------+----------------+---------------+----------------------------------+ +// +// +// ๐ŸŒŸ This was machine generated. Do not edit. ๐ŸŒŸ +{ + "frames": [ + { + "schema": { + "name": "raw", + "fields": [ + { + "name": "uid", + "type": "string", + "typeInfo": { + "frame": "string" + } + }, + { + "name": "kind", + "type": "string", + "typeInfo": { + "frame": "string" + } + }, + { + "name": "size", + "type": "number", + "typeInfo": { + "frame": "int64" + } + }, + { + "name": "etag", + "type": "string", + "typeInfo": { + "frame": "string" + } + } + ] + }, + "data": { + "values": [ + [ + "alerting/testdata_alerts.json", + "all-panels.json", + "datasource-elasticsearch/elasticsearch_compare.json", + "datasource-elasticsearch/elasticsearch_v7.json", + "datasource-elasticsearch/elasticsearch_v7_filebeat.json", + "datasource-influxdb/influxdb-logs.json", + "datasource-influxdb/influxdb-templated.json", + "datasource-mssql/mssql_fakedata.json", + "datasource-mssql/mssql_unittest.json", + "datasource-mysql/mysql_fakedata.json", + "datasource-mysql/mysql_unittest.json", + "datasource-opentsdb/opentsdb.json", + "datasource-opentsdb/opentsdb_v2.3.json", + "datasource-postgres/postgres_fakedata.json", + "datasource-postgres/postgres_unittest.json", + "datasource-testdata/bar-gauge-demo2.json", + "datasource-testdata/demo1.json", + "datasource-testdata/new_features_in_v62.json", + "datasource-testdata/new_features_in_v74.json", + "datasource-testdata/new_features_in_v8.json", + "e2e-repeats/Repeating-Kitchen-Sink.json", + "e2e-repeats/Repeating-a-panel-horizontally.json", + "e2e-repeats/Repeating-a-panel-vertically.json", + "e2e-repeats/Repeating-a-row-with-a-non-repeating-panel-and-horizontal-repeating-panel.json", + "e2e-repeats/Repeating-a-row-with-a-non-repeating-panel-and-vertical-repeating-panel.json", + "e2e-repeats/Repeating-a-row-with-a-non-repeating-panel.json", + "e2e-repeats/Repeating-a-row-with-a-repeating-horizontal-panel.json", + "e2e-repeats/Repeating-a-row-with-a-repeating-vertical-panel.json", + "e2e-repeats/Repeating-an-empty-row.json", + "feature-templating/global-variables-and-interpolation.json", + "feature-templating/templating-dashboard-links-and-variables.json", + "feature-templating/templating-textbox-e2e-scenarios.json", + "feature-templating/testdata-datalinks.json", + "feature-templating/testdata-nested-variables-drilldown.json", + "feature-templating/testdata-nested-variables.json", + "feature-templating/testdata-repeating.json", + "feature-templating/testdata-test-variable-output.json", + "feature-templating/testdata-variables-textbox.json", + "feature-templating/testdata-variables-that-update-on-time-change.json", + "home.json", + "panel-barchart/barchart-autosizing.json", + "panel-bargauge/bar_gauge_demo.json", + "panel-bargauge/panel_tests_bar_gauge.json", + "panel-bargauge/panel_tests_bar_gauge2.json", + "panel-candlestick/candlestick.json", + "panel-common/auto_decimals.json", + "panel-common/color_modes.json", + "panel-common/lazy_loading.json", + "panel-common/linked-viz.json", + "panel-common/panels_without_title.json", + "panel-common/shared_queries.json", + "panel-gauge/gauge-multi-series.json", + "panel-gauge/gauge_tests.json", + "panel-geomap/geomap-9.1.json", + "panel-geomap/geomap-color-field.json", + "panel-geomap/geomap-spatial-operations-transformer.json", + "panel-geomap/geomap_multi-layers.json", + "panel-geomap/panel-geomap.json", + "panel-graph/graph-gradient-area-fills.json", + "panel-graph/graph-ng-by-value-color-schemes.json", + "panel-graph/graph-ng-gradient-area.json", + "panel-graph/graph-ng-hue-gradients.json", + "panel-graph/graph-ng-nulls.json", + "panel-graph/graph-ng-soft-limits.json", + "panel-graph/graph-ng-stacking.json", + "panel-graph/graph-ng-stacking2.json", + "panel-graph/graph-ng-thresholds.json", + "panel-graph/graph-ng-time.json", + "panel-graph/graph-ng-y-ticks-zero-decimals.json", + "panel-graph/graph-ng-yaxis-ticks.json", + "panel-graph/graph-ng.json", + "panel-graph/graph-shared-tooltip-cursor-position.json", + "panel-graph/graph-shared-tooltips.json", + "panel-graph/graph-time-regions.json", + "panel-graph/graph_tests.json", + "panel-graph/graph_y_axis.json", + "panel-heatmap/heatmap-calculate-log.json", + "panel-heatmap/heatmap-legacy.json", + "panel-histogram/histogram_tests.json", + "panel-library/panel-library.json", + "panel-piechart/panel_test_piechart.json", + "panel-polystat/polystat_test.json", + "panel-stat/panel-stat-tests.json", + "panel-table/table_pagination.json", + "panel-table/table_tests.json", + "panel-table/table_tests_new.json", + "panel-text/text-options.json", + "panel-timeline/timeline-demo.json", + "panel-timeline/timeline-modes.json", + "scenarios/slow_queries_and_annotations.json", + "scenarios/time_zone_support.json", + "transforms/config-from-query.json", + "transforms/join-by-field.json", + "transforms/join-by-labels.json", + "transforms/reuse.json", + "transforms/rows-to-fields.json" + ], + [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ], + [ + 16402, + 23018, + 284527, + 16554, + 5411, + 4052, + 7571, + 13821, + 67893, + 13790, + 61999, + 4560, + 5098, + 14763, + 61778, + 10392, + 25047, + 28885, + 52379, + 68285, + 10694, + 4374, + 4268, + 7367, + 7213, + 5386, + 5467, + 5437, + 3644, + 3418, + 2672, + 2302, + 12563, + 6785, + 12210, + 30599, + 1416, + 5082, + 4373, + 5021, + 14764, + 14383, + 17936, + 11716, + 11649, + 24938, + 7435, + 46665, + 25513, + 19363, + 6908, + 5779, + 30214, + 7994, + 11109, + 2558, + 12115, + 10579, + 7932, + 19829, + 13044, + 20472, + 34841, + 71730, + 27339, + 92679, + 28016, + 10751, + 21473, + 16810, + 78597, + 13213, + 17326, + 12850, + 36654, + 17281, + 17917, + 8486, + 9846, + 3555, + 10837, + 77949, + 17284, + 187375, + 11809, + 14609, + 7122, + 10777, + 8674, + 24166, + 15128, + 13876, + 13415, + 7421, + 13651, + 14336 + ], + [ + "a3679c3611fc3a83b0a9418e8f4cd0eb", + "a52c6dab16ecc2d3fd0b1e1edad930d6", + "394573393efa229fb0b8a3630e177c6d", + "68b3570b21e53cec3d3514ba222948a3", + "e9c22bae37ecf4e8c031a6fd39f8bfe5", + "65b5cc531e621170e6a1a8ed4b04a7ca", + "3aedc5a23691a50adff0d7d8e2d8ed43", + "38d1fe0cecdbfc4c0e733f88250c74f7", + "7d2f553e07ef2a0b06201fb93ed22753", + "5471e2fef40e9dc4b76720d93510a501", + "b6e257f846aa7f2a2e55300191184fd0", + "9b0525acc3d7ca36bcaf3997a6f3c1ff", + "2ddb1868bfd0403a6fefe0b683bda29d", + "ee5a205b505322e998ab8c615c339152", + "d44a5bdfd6ed8a17c9eb3aa80065fabc", + "b1e00795b3743700f17f367231488fb6", + "95e80f6c9fe1411e563f28d8c01fae0c", + "4508571900d67d6e0f6588163ff49fe8", + "5304a1c407dd3dd96e15ff63d0341275", + "1332fc78110cf02fcab7ffdf336a9b57", + "d711c9928dbd6ccd23f69ffda93db7c5", + "7914d26e815c46df3c43c16c05b7d9d2", + "caeb61cc63377bfe3d1791e32e6300bc", + "d71d307d359f20e0966c335705aac429", + "1b759c2c04c42e61516a41f123167bf1", + "04c83a8e2d50cdfbb1d793e713c63a09", + "8aa7d037eec6477697068ca26d87818c", + "4432b82e3347f3ffcc5ce80c8fafc39e", + "cf1c322ca66595a469b3b81b3be9c900", + "8d964fd60dd43bebb5b6f5605716cf43", + "e3187144de4cff19fc7223283a370383", + "d01ba1b63b4870b37ffa26ed5ea7d28d", + "c7c8fc2a559166d538d14e6d3ac89f20", + "e75f137162d5680535c8805e1baaeac5", + "0fc23e0309a1c5ca5d57daf10a17f216", + "c437a6eb31c56d64fd345511b88c7498", + "e5966b4e4b12799b0e0552c7d3b81e0f", + "6c5003d28ea56d3d499e609dd50f5ad1", + "db1b17c792f99aefa6b7a80e403b62c0", + "be062e1c3e2033ef46a336bf0c3f5172", + "47bb83a81a4427673953126f034f2c09", + "7beae673d7fb55ece2ab0169ac8bf04c", + "b4853b38464f95d79f1b7f893a9a6a4f", + "080701565677d45165d2aca1d199c4cc", + "34f9cec2e1e44c45ca9ccdd6806e7750", + "2901f2bbcefb0b20d09c59750e4ceecd", + "305262c474aa436622235d50d6120f2b", + "4f8be9860297e38156781c132d8a2868", + "b7b458cabfa95b39d2a5158ebd757196", + "07dbfaa2f24c8f962028c42b4581a32a", + "f91beba659e201cdad84a158a9c67d16", + "4baab5779296c37c0c7227785b8dff26", + "10253cb1b18530244bf7ed5644c264b2", + "a74935c18fdeeea0bb5feb75e5ce38e8", + "fcd97448c0e9760d1c0a29ec5fd65c61", + "0102316d0725a3de3bb4d943ab8e735b", + "1da95824843a317223faa5e06cc50fd4", + "53a1f9af752491d429439cff6fa4f96d", + "43b962717f08ddc5347350620d084329", + "722fd9e83a671f881d89d4fcc8d0ccfc", + "d63e2f87ac9816f06b3afee1632dd2a0", + "566ca0e071cd3a992fd978648ca807ab", + "37daa49f2913fd329d5e33f1da3f4e7a", + "84d7fc19be0eefaffae1b882efa4388f", + "18c8037c2781381478aed7fd2fe5b4f6", + "9910843bdd5205cbda2cb5dd01673c90", + "5c2edf32997b1578e29cdd27f3ab4eda", + "898cbd382354c3d785011197de3abdd4", + "a0bed022d7309e665c97ff3049e1b495", + "7204212079a9c5d020cf956cd7782267", + "d5805d2754f152163bcf2d5805214080", + "fa9dd510a6ca45ff919d804082c2e206", + "7e672ee13c5baa7d34f14f77bd73bb62", + "aec241e9c1c88b8d60b0cbe078cc099b", + "0271f13106f164b7a4f010b2d9debad3", + "77217ddc8a2ff5870c8d9442072834be", + "ecdb79040e0097ff27c9875053388885", + "f84915e2d5d78634f299ca3268596777", + "1b51cd57d4c1dc5f4bf5bb7fedcbac50", + "981a5c32a28f2fd036d9b9ee6a8a5cbe", + "debdfbf85cf8995cd7c031abc10d2ba8", + "cb2082425856905f58825ad653e70497", + "4c7b95f270dc1ceaeec389e528cfe196", + "56a87f3dd441ed107b8ad19c737254a7", + "2ef3da58c15a6de2fc57788c879c67a6", + "04ec32ff7d310d76b5fee4fa3e53bfc4", + "f6ea799109bb78d2f2954947a188d7b6", + "dfcd599be6b6df94aef3b6da9d8ac3fb", + "21dd0f87426cf7afc030d688d5516178", + "727c2c46deddeb164cd9ce36a0ec1567", + "f517e61f40152e16f3291e72c27f606d", + "c1cbaf503457216461032844f47ac065", + "e75680578202a10545c4c09b4ba28c3e", + "47ac2804c2cfe7067302804e4835ef87", + "8a7925616b92e611a99f3a1adde1f712", + "03d54e79d5d293e00559a4022905f0c8" + ] + ] + } + } + ] +} \ No newline at end of file diff --git a/pkg/services/searchV2/object/testdata/dash_references.jsonc b/pkg/services/searchV2/object/testdata/dash_references.jsonc new file mode 100644 index 00000000000..80213368d6b --- /dev/null +++ b/pkg/services/searchV2/object/testdata/dash_references.jsonc @@ -0,0 +1,1239 @@ +// ๐ŸŒŸ This was machine generated. Do not edit. ๐ŸŒŸ +// +// Frame[0] +// Name: references +// Dimensions: 4 Fields by 291 Rows +// +-------------------------------+----------------+----------------+----------------+ +// | Name: uid | Name: kind | Name: type | Name: uid | +// | Labels: | Labels: | Labels: | Labels: | +// | Type: []string | Type: []string | Type: []string | Type: []string | +// +-------------------------------+----------------+----------------+----------------+ +// | alerting/testdata_alerts.json | ds | default.type | default.uid | +// | alerting/testdata_alerts.json | panel | alertlist | | +// | alerting/testdata_alerts.json | panel | graph | | +// | all-panels.json | ds | default.type | default.uid | +// | all-panels.json | panel | alertlist | | +// | all-panels.json | panel | annolist | | +// | all-panels.json | panel | barchart | | +// | all-panels.json | panel | bargauge | | +// | all-panels.json | panel | dashlist | | +// | ... | ... | ... | ... | +// +-------------------------------+----------------+----------------+----------------+ +// +// +// ๐ŸŒŸ This was machine generated. Do not edit. ๐ŸŒŸ +{ + "frames": [ + { + "schema": { + "name": "references", + "fields": [ + { + "name": "uid", + "type": "string", + "typeInfo": { + "frame": "string" + } + }, + { + "name": "kind", + "type": "string", + "typeInfo": { + "frame": "string" + } + }, + { + "name": "type", + "type": "string", + "typeInfo": { + "frame": "string" + } + }, + { + "name": "uid", + "type": "string", + "typeInfo": { + "frame": "string" + } + } + ] + }, + "data": { + "values": [ + [ + "alerting/testdata_alerts.json", + "alerting/testdata_alerts.json", + "alerting/testdata_alerts.json", + "all-panels.json", + "all-panels.json", + "all-panels.json", + "all-panels.json", + "all-panels.json", + "all-panels.json", + "all-panels.json", + "all-panels.json", + "all-panels.json", + "all-panels.json", + "all-panels.json", + "all-panels.json", + "all-panels.json", + "all-panels.json", + "all-panels.json", + "all-panels.json", + "all-panels.json", + "all-panels.json", + "all-panels.json", + "datasource-elasticsearch/elasticsearch_compare.json", + "datasource-elasticsearch/elasticsearch_compare.json", + "datasource-elasticsearch/elasticsearch_compare.json", + "datasource-elasticsearch/elasticsearch_v7.json", + "datasource-elasticsearch/elasticsearch_v7.json", + "datasource-elasticsearch/elasticsearch_v7.json", + "datasource-elasticsearch/elasticsearch_v7.json", + "datasource-elasticsearch/elasticsearch_v7_filebeat.json", + "datasource-elasticsearch/elasticsearch_v7_filebeat.json", + "datasource-elasticsearch/elasticsearch_v7_filebeat.json", + "datasource-influxdb/influxdb-logs.json", + "datasource-influxdb/influxdb-logs.json", + "datasource-influxdb/influxdb-logs.json", + "datasource-influxdb/influxdb-templated.json", + "datasource-influxdb/influxdb-templated.json", + "datasource-mssql/mssql_fakedata.json", + "datasource-mssql/mssql_fakedata.json", + "datasource-mssql/mssql_fakedata.json", + "datasource-mssql/mssql_unittest.json", + "datasource-mssql/mssql_unittest.json", + "datasource-mssql/mssql_unittest.json", + "datasource-mysql/mysql_fakedata.json", + "datasource-mysql/mysql_fakedata.json", + "datasource-mysql/mysql_fakedata.json", + "datasource-mysql/mysql_unittest.json", + "datasource-mysql/mysql_unittest.json", + "datasource-mysql/mysql_unittest.json", + "datasource-opentsdb/opentsdb.json", + "datasource-opentsdb/opentsdb.json", + "datasource-opentsdb/opentsdb_v2.3.json", + "datasource-opentsdb/opentsdb_v2.3.json", + "datasource-postgres/postgres_fakedata.json", + "datasource-postgres/postgres_fakedata.json", + "datasource-postgres/postgres_fakedata.json", + "datasource-postgres/postgres_unittest.json", + "datasource-postgres/postgres_unittest.json", + "datasource-postgres/postgres_unittest.json", + "datasource-testdata/bar-gauge-demo2.json", + "datasource-testdata/bar-gauge-demo2.json", + "datasource-testdata/demo1.json", + "datasource-testdata/demo1.json", + "datasource-testdata/demo1.json", + "datasource-testdata/new_features_in_v62.json", + "datasource-testdata/new_features_in_v62.json", + "datasource-testdata/new_features_in_v62.json", + "datasource-testdata/new_features_in_v62.json", + "datasource-testdata/new_features_in_v62.json", + "datasource-testdata/new_features_in_v62.json", + "datasource-testdata/new_features_in_v62.json", + "datasource-testdata/new_features_in_v74.json", + "datasource-testdata/new_features_in_v74.json", + "datasource-testdata/new_features_in_v74.json", + "datasource-testdata/new_features_in_v74.json", + "datasource-testdata/new_features_in_v8.json", + "datasource-testdata/new_features_in_v8.json", + "datasource-testdata/new_features_in_v8.json", + "datasource-testdata/new_features_in_v8.json", + "datasource-testdata/new_features_in_v8.json", + "datasource-testdata/new_features_in_v8.json", + "datasource-testdata/new_features_in_v8.json", + "datasource-testdata/new_features_in_v8.json", + "e2e-repeats/Repeating-Kitchen-Sink.json", + "e2e-repeats/Repeating-Kitchen-Sink.json", + "e2e-repeats/Repeating-Kitchen-Sink.json", + "e2e-repeats/Repeating-a-panel-horizontally.json", + "e2e-repeats/Repeating-a-panel-horizontally.json", + "e2e-repeats/Repeating-a-panel-vertically.json", + "e2e-repeats/Repeating-a-panel-vertically.json", + "e2e-repeats/Repeating-a-row-with-a-non-repeating-panel-and-horizontal-repeating-panel.json", + "e2e-repeats/Repeating-a-row-with-a-non-repeating-panel-and-horizontal-repeating-panel.json", + "e2e-repeats/Repeating-a-row-with-a-non-repeating-panel-and-horizontal-repeating-panel.json", + "e2e-repeats/Repeating-a-row-with-a-non-repeating-panel-and-vertical-repeating-panel.json", + "e2e-repeats/Repeating-a-row-with-a-non-repeating-panel-and-vertical-repeating-panel.json", + "e2e-repeats/Repeating-a-row-with-a-non-repeating-panel-and-vertical-repeating-panel.json", + "e2e-repeats/Repeating-a-row-with-a-non-repeating-panel.json", + "e2e-repeats/Repeating-a-row-with-a-non-repeating-panel.json", + "e2e-repeats/Repeating-a-row-with-a-non-repeating-panel.json", + "e2e-repeats/Repeating-a-row-with-a-repeating-horizontal-panel.json", + "e2e-repeats/Repeating-a-row-with-a-repeating-horizontal-panel.json", + "e2e-repeats/Repeating-a-row-with-a-repeating-horizontal-panel.json", + "e2e-repeats/Repeating-a-row-with-a-repeating-vertical-panel.json", + "e2e-repeats/Repeating-a-row-with-a-repeating-vertical-panel.json", + "e2e-repeats/Repeating-a-row-with-a-repeating-vertical-panel.json", + "e2e-repeats/Repeating-an-empty-row.json", + "feature-templating/global-variables-and-interpolation.json", + "feature-templating/global-variables-and-interpolation.json", + "feature-templating/templating-dashboard-links-and-variables.json", + "feature-templating/templating-dashboard-links-and-variables.json", + "feature-templating/templating-textbox-e2e-scenarios.json", + "feature-templating/templating-textbox-e2e-scenarios.json", + "feature-templating/testdata-datalinks.json", + "feature-templating/testdata-datalinks.json", + "feature-templating/testdata-datalinks.json", + "feature-templating/testdata-datalinks.json", + "feature-templating/testdata-datalinks.json", + "feature-templating/testdata-nested-variables-drilldown.json", + "feature-templating/testdata-nested-variables-drilldown.json", + "feature-templating/testdata-nested-variables-drilldown.json", + "feature-templating/testdata-nested-variables-drilldown.json", + "feature-templating/testdata-nested-variables.json", + "feature-templating/testdata-nested-variables.json", + "feature-templating/testdata-nested-variables.json", + "feature-templating/testdata-nested-variables.json", + "feature-templating/testdata-nested-variables.json", + "feature-templating/testdata-nested-variables.json", + "feature-templating/testdata-nested-variables.json", + "feature-templating/testdata-repeating.json", + "feature-templating/testdata-repeating.json", + "feature-templating/testdata-repeating.json", + "feature-templating/testdata-test-variable-output.json", + "feature-templating/testdata-test-variable-output.json", + "feature-templating/testdata-variables-textbox.json", + "feature-templating/testdata-variables-textbox.json", + "feature-templating/testdata-variables-textbox.json", + "feature-templating/testdata-variables-that-update-on-time-change.json", + "feature-templating/testdata-variables-that-update-on-time-change.json", + "home.json", + "home.json", + "panel-barchart/barchart-autosizing.json", + "panel-barchart/barchart-autosizing.json", + "panel-bargauge/bar_gauge_demo.json", + "panel-bargauge/bar_gauge_demo.json", + "panel-bargauge/panel_tests_bar_gauge.json", + "panel-bargauge/panel_tests_bar_gauge.json", + "panel-bargauge/panel_tests_bar_gauge2.json", + "panel-bargauge/panel_tests_bar_gauge2.json", + "panel-candlestick/candlestick.json", + "panel-candlestick/candlestick.json", + "panel-common/auto_decimals.json", + "panel-common/auto_decimals.json", + "panel-common/color_modes.json", + "panel-common/color_modes.json", + "panel-common/color_modes.json", + "panel-common/color_modes.json", + "panel-common/lazy_loading.json", + "panel-common/lazy_loading.json", + "panel-common/lazy_loading.json", + "panel-common/lazy_loading.json", + "panel-common/linked-viz.json", + "panel-common/linked-viz.json", + "panel-common/linked-viz.json", + "panel-common/linked-viz.json", + "panel-common/panels_without_title.json", + "panel-common/panels_without_title.json", + "panel-common/panels_without_title.json", + "panel-common/panels_without_title.json", + "panel-common/panels_without_title.json", + "panel-common/panels_without_title.json", + "panel-common/shared_queries.json", + "panel-common/shared_queries.json", + "panel-common/shared_queries.json", + "panel-common/shared_queries.json", + "panel-common/shared_queries.json", + "panel-gauge/gauge-multi-series.json", + "panel-gauge/gauge-multi-series.json", + "panel-gauge/gauge_tests.json", + "panel-gauge/gauge_tests.json", + "panel-gauge/gauge_tests.json", + "panel-geomap/geomap-9.1.json", + "panel-geomap/geomap-9.1.json", + "panel-geomap/geomap-color-field.json", + "panel-geomap/geomap-color-field.json", + "panel-geomap/geomap-color-field.json", + "panel-geomap/geomap-color-field.json", + "panel-geomap/geomap-spatial-operations-transformer.json", + "panel-geomap/geomap-spatial-operations-transformer.json", + "panel-geomap/geomap_multi-layers.json", + "panel-geomap/geomap_multi-layers.json", + "panel-geomap/panel-geomap.json", + "panel-geomap/panel-geomap.json", + "panel-graph/graph-gradient-area-fills.json", + "panel-graph/graph-gradient-area-fills.json", + "panel-graph/graph-ng-by-value-color-schemes.json", + "panel-graph/graph-ng-by-value-color-schemes.json", + "panel-graph/graph-ng-gradient-area.json", + "panel-graph/graph-ng-gradient-area.json", + "panel-graph/graph-ng-hue-gradients.json", + "panel-graph/graph-ng-hue-gradients.json", + "panel-graph/graph-ng-nulls.json", + "panel-graph/graph-ng-nulls.json", + "panel-graph/graph-ng-soft-limits.json", + "panel-graph/graph-ng-soft-limits.json", + "panel-graph/graph-ng-stacking.json", + "panel-graph/graph-ng-stacking.json", + "panel-graph/graph-ng-stacking2.json", + "panel-graph/graph-ng-stacking2.json", + "panel-graph/graph-ng-stacking2.json", + "panel-graph/graph-ng-thresholds.json", + "panel-graph/graph-ng-thresholds.json", + "panel-graph/graph-ng-thresholds.json", + "panel-graph/graph-ng-time.json", + "panel-graph/graph-ng-time.json", + "panel-graph/graph-ng-y-ticks-zero-decimals.json", + "panel-graph/graph-ng-y-ticks-zero-decimals.json", + "panel-graph/graph-ng-yaxis-ticks.json", + "panel-graph/graph-ng-yaxis-ticks.json", + "panel-graph/graph-ng.json", + "panel-graph/graph-ng.json", + "panel-graph/graph-ng.json", + "panel-graph/graph-shared-tooltip-cursor-position.json", + "panel-graph/graph-shared-tooltip-cursor-position.json", + "panel-graph/graph-shared-tooltips.json", + "panel-graph/graph-shared-tooltips.json", + "panel-graph/graph-shared-tooltips.json", + "panel-graph/graph-shared-tooltips.json", + "panel-graph/graph-shared-tooltips.json", + "panel-graph/graph-time-regions.json", + "panel-graph/graph-time-regions.json", + "panel-graph/graph_tests.json", + "panel-graph/graph_tests.json", + "panel-graph/graph_tests.json", + "panel-graph/graph_y_axis.json", + "panel-graph/graph_y_axis.json", + "panel-heatmap/heatmap-calculate-log.json", + "panel-heatmap/heatmap-calculate-log.json", + "panel-heatmap/heatmap-calculate-log.json", + "panel-heatmap/heatmap-legacy.json", + "panel-heatmap/heatmap-legacy.json", + "panel-histogram/histogram_tests.json", + "panel-histogram/histogram_tests.json", + "panel-histogram/histogram_tests.json", + "panel-library/panel-library.json", + "panel-library/panel-library.json", + "panel-library/panel-library.json", + "panel-piechart/panel_test_piechart.json", + "panel-piechart/panel_test_piechart.json", + "panel-polystat/polystat_test.json", + "panel-polystat/polystat_test.json", + "panel-stat/panel-stat-tests.json", + "panel-stat/panel-stat-tests.json", + "panel-table/table_pagination.json", + "panel-table/table_pagination.json", + "panel-table/table_tests.json", + "panel-table/table_tests.json", + "panel-table/table_tests_new.json", + "panel-table/table_tests_new.json", + "panel-table/table_tests_new.json", + "panel-text/text-options.json", + "panel-text/text-options.json", + "panel-timeline/timeline-demo.json", + "panel-timeline/timeline-demo.json", + "panel-timeline/timeline-demo.json", + "panel-timeline/timeline-modes.json", + "panel-timeline/timeline-modes.json", + "panel-timeline/timeline-modes.json", + "scenarios/slow_queries_and_annotations.json", + "scenarios/slow_queries_and_annotations.json", + "scenarios/time_zone_support.json", + "scenarios/time_zone_support.json", + "transforms/config-from-query.json", + "transforms/config-from-query.json", + "transforms/config-from-query.json", + "transforms/config-from-query.json", + "transforms/join-by-field.json", + "transforms/join-by-field.json", + "transforms/join-by-field.json", + "transforms/join-by-field.json", + "transforms/join-by-labels.json", + "transforms/join-by-labels.json", + "transforms/join-by-labels.json", + "transforms/reuse.json", + "transforms/reuse.json", + "transforms/reuse.json", + "transforms/reuse.json", + "transforms/rows-to-fields.json", + "transforms/rows-to-fields.json", + "transforms/rows-to-fields.json", + "transforms/rows-to-fields.json", + "transforms/rows-to-fields.json" + ], + [ + "ds", + "panel", + "panel", + "ds", + "panel", + "panel", + "panel", + "panel", + "panel", + "panel", + "panel", + "panel", + "panel", + "panel", + "panel", + "panel", + "panel", + "panel", + "panel", + "panel", + "panel", + "panel", + "ds", + "panel", + "panel", + "ds", + "panel", + "panel", + "panel", + "ds", + "panel", + "panel", + "ds", + "panel", + "panel", + "ds", + "panel", + "ds", + "panel", + "panel", + "ds", + "panel", + "panel", + "ds", + "panel", + "panel", + "ds", + "panel", + "panel", + "ds", + "panel", + "ds", + "panel", + "ds", + "panel", + "panel", + "ds", + "panel", + "panel", + "ds", + "panel", + "ds", + "panel", + "panel", + "ds", + "panel", + "panel", + "panel", + "panel", + "panel", + "panel", + "ds", + "panel", + "panel", + "panel", + "ds", + "panel", + "panel", + "panel", + "panel", + "panel", + "panel", + "panel", + "ds", + "panel", + "panel", + "ds", + "panel", + "ds", + "panel", + "ds", + "panel", + "panel", + "ds", + "panel", + "panel", + "ds", + "panel", + "panel", + "ds", + "panel", + "panel", + "ds", + "panel", + "panel", + "panel", + "ds", + "panel", + "ds", + "panel", + "ds", + "panel", + "ds", + "panel", + "panel", + "panel", + "panel", + "ds", + "panel", + "panel", + "panel", + "ds", + "panel", + "panel", + "panel", + "panel", + "panel", + "panel", + "ds", + "panel", + "panel", + "ds", + "panel", + "ds", + "panel", + "panel", + "ds", + "panel", + "ds", + "panel", + "ds", + "panel", + "ds", + "panel", + "ds", + "panel", + "ds", + "panel", + "ds", + "panel", + "ds", + "panel", + "ds", + "panel", + "panel", + "panel", + "ds", + "panel", + "panel", + "panel", + "ds", + "panel", + "panel", + "panel", + "ds", + "panel", + "panel", + "panel", + "panel", + "panel", + "ds", + "panel", + "panel", + "panel", + "panel", + "ds", + "panel", + "ds", + "panel", + "panel", + "ds", + "panel", + "ds", + "panel", + "panel", + "panel", + "ds", + "panel", + "ds", + "panel", + "ds", + "panel", + "ds", + "panel", + "ds", + "panel", + "ds", + "panel", + "ds", + "panel", + "ds", + "panel", + "ds", + "panel", + "ds", + "panel", + "ds", + "panel", + "panel", + "ds", + "panel", + "panel", + "ds", + "panel", + "ds", + "panel", + "ds", + "panel", + "ds", + "panel", + "panel", + "ds", + "panel", + "ds", + "panel", + "panel", + "panel", + "panel", + "ds", + "panel", + "ds", + "panel", + "panel", + "ds", + "panel", + "ds", + "panel", + "panel", + "ds", + "panel", + "ds", + "panel", + "panel", + "ds", + "panel", + "panel", + "ds", + "panel", + "ds", + "panel", + "ds", + "panel", + "ds", + "panel", + "ds", + "panel", + "ds", + "panel", + "panel", + "ds", + "panel", + "ds", + "panel", + "panel", + "ds", + "panel", + "panel", + "ds", + "panel", + "ds", + "panel", + "ds", + "panel", + "panel", + "panel", + "ds", + "panel", + "panel", + "panel", + "ds", + "panel", + "panel", + "ds", + "panel", + "panel", + "panel", + "ds", + "panel", + "panel", + "panel", + "panel" + ], + [ + "default.type", + "alertlist", + "graph", + "default.type", + "alertlist", + "annolist", + "barchart", + "bargauge", + "dashlist", + "gauge", + "geomap", + "heatmap", + "histogram", + "logs", + "news", + "piechart", + "row", + "stat", + "state-timeline", + "table", + "text", + "timeseries", + "default.type", + "row", + "timeseries", + "default.type", + "grafana-worldmap-panel", + "graph", + "table-old", + "default.type", + "graph", + "logs", + "default.type", + "graph", + "logs", + "default.type", + "graph", + "default.type", + "graph", + "table", + "default.type", + "graph", + "table", + "default.type", + "graph", + "table", + "default.type", + "graph", + "table", + "default.type", + "graph", + "default.type", + "graph", + "default.type", + "graph", + "table", + "default.type", + "graph", + "table", + "default.type", + "bargauge", + "default.type", + "graph", + "singlestat", + "default.type", + "bargauge", + "gauge", + "graph", + "row", + "singlestat", + "text", + "default.type", + "row", + "text", + "timeseries", + "default.type", + "barchart", + "histogram", + "state-timeline", + "status-history", + "table", + "text", + "timeseries", + "default.type", + "row", + "timeseries", + "default.type", + "timeseries", + "default.type", + "timeseries", + "default.type", + "row", + "timeseries", + "default.type", + "row", + "timeseries", + "default.type", + "row", + "timeseries", + "default.type", + "row", + "timeseries", + "default.type", + "row", + "timeseries", + "row", + "default.type", + "text", + "default.type", + "text", + "default.type", + "text", + "default.type", + "bargauge", + "gauge", + "graph", + "text", + "default.type", + "graph", + "singlestat", + "text", + "default.type", + "bargauge", + "gauge", + "graph", + "singlestat", + "table", + "text", + "default.type", + "gauge", + "singlestat", + "default.type", + "text", + "default.type", + "graph", + "table", + "default.type", + "graph", + "default.type", + "dashlist", + "default.type", + "barchart", + "default.type", + "bargauge", + "default.type", + "bargauge", + "default.type", + "bargauge", + "default.type", + "candlestick", + "default.type", + "graph", + "default.type", + "bargauge", + "stat", + "table", + "default.type", + "bargauge", + "graph", + "singlestat", + "default.type", + "bargauge", + "gauge", + "stat", + "default.type", + "bargauge", + "gauge", + "graph", + "singlestat", + "text2", + "default.type", + "bargauge", + "gauge", + "graph", + "table", + "default.type", + "gauge", + "default.type", + "gauge", + "row", + "default.type", + "geomap", + "default.type", + "geomap", + "stat", + "table", + "default.type", + "geomap", + "default.type", + "geomap", + "default.type", + "geomap", + "default.type", + "graph", + "default.type", + "timeseries", + "default.type", + "timeseries", + "default.type", + "timeseries", + "default.type", + "timeseries", + "default.type", + "timeseries", + "default.type", + "timeseries", + "default.type", + "barchart", + "timeseries", + "default.type", + "graph", + "timeseries", + "default.type", + "timeseries", + "default.type", + "timeseries", + "default.type", + "timeseries", + "default.type", + "row", + "timeseries", + "default.type", + "timeseries", + "default.type", + "debug", + "graph", + "timeseries", + "xychart", + "default.type", + "graph", + "default.type", + "graph", + "text", + "default.type", + "graph", + "default.type", + "heatmap", + "timeseries", + "default.type", + "heatmap", + "default.type", + "histogram", + "table", + "default.type", + "", + "graph", + "default.type", + "piechart", + "default.type", + "grafana-polystat-panel", + "default.type", + "stat", + "default.type", + "table", + "default.type", + "table", + "default.type", + "row", + "table", + "default.type", + "text", + "default.type", + "state-timeline", + "status-history", + "default.type", + "state-timeline", + "status-history", + "default.type", + "graph", + "default.type", + "graph", + "default.type", + "barchart", + "table", + "timeseries", + "default.type", + "row", + "table", + "timeseries", + "default.type", + "stat", + "table", + "default.type", + "geomap", + "table", + "text", + "default.type", + "bargauge", + "gauge", + "stat", + "table" + ], + [ + "default.uid", + "", + "", + "default.uid", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "default.uid", + "", + "", + "default.uid", + "", + "", + "", + "default.uid", + "", + "", + "default.uid", + "", + "", + "default.uid", + "", + "default.uid", + "", + "", + "default.uid", + "", + "", + "default.uid", + "", + "", + "default.uid", + "", + "", + "default.uid", + "", + "default.uid", + "", + "default.uid", + "", + "", + "default.uid", + "", + "", + "default.uid", + "", + "default.uid", + "", + "", + "default.uid", + "", + "", + "", + "", + "", + "", + "default.uid", + "", + "", + "", + "default.uid", + "", + "", + "", + "", + "", + "", + "", + "default.uid", + "", + "", + "default.uid", + "", + "default.uid", + "", + "default.uid", + "", + "", + "default.uid", + "", + "", + "default.uid", + "", + "", + "default.uid", + "", + "", + "default.uid", + "", + "", + "", + "default.uid", + "", + "default.uid", + "", + "default.uid", + "", + "default.uid", + "", + "", + "", + "", + "default.uid", + "", + "", + "", + "default.uid", + "", + "", + "", + "", + "", + "", + "default.uid", + "", + "", + "default.uid", + "", + "default.uid", + "", + "", + "default.uid", + "", + "default.uid", + "", + "default.uid", + "", + "default.uid", + "", + "default.uid", + "", + "default.uid", + "", + "default.uid", + "", + "default.uid", + "", + "default.uid", + "", + "", + "", + "default.uid", + "", + "", + "", + "default.uid", + "", + "", + "", + "default.uid", + "", + "", + "", + "", + "", + "default.uid", + "", + "", + "", + "", + "default.uid", + "", + "default.uid", + "", + "", + "default.uid", + "", + "default.uid", + "", + "", + "", + "default.uid", + "", + "default.uid", + "", + "default.uid", + "", + "default.uid", + "", + "default.uid", + "", + "default.uid", + "", + "default.uid", + "", + "default.uid", + "", + "default.uid", + "", + "default.uid", + "", + "default.uid", + "", + "", + "default.uid", + "", + "", + "default.uid", + "", + "default.uid", + "", + "default.uid", + "", + "default.uid", + "", + "", + "default.uid", + "", + "default.uid", + "", + "", + "", + "", + "default.uid", + "", + "default.uid", + "", + "", + "default.uid", + "", + "default.uid", + "", + "", + "default.uid", + "", + "default.uid", + "", + "", + "default.uid", + "", + "", + "default.uid", + "", + "default.uid", + "", + "default.uid", + "", + "default.uid", + "", + "default.uid", + "", + "default.uid", + "", + "", + "default.uid", + "", + "default.uid", + "", + "", + "default.uid", + "", + "", + "default.uid", + "", + "default.uid", + "", + "default.uid", + "", + "", + "", + "default.uid", + "", + "", + "", + "default.uid", + "", + "", + "default.uid", + "", + "", + "", + "default.uid", + "", + "", + "", + "" + ] + ] + } + } + ] +} \ No newline at end of file diff --git a/pkg/services/searchV2/object/testdata/dash_summary.jsonc b/pkg/services/searchV2/object/testdata/dash_summary.jsonc new file mode 100644 index 00000000000..a90c22afdd9 --- /dev/null +++ b/pkg/services/searchV2/object/testdata/dash_summary.jsonc @@ -0,0 +1,418 @@ +// ๐ŸŒŸ This was machine generated. Do not edit. ๐ŸŒŸ +// +// Frame[0] +// Name: summary +// Dimensions: 3 Fields by 96 Rows +// +---------------------------------------------------------+----------------------------------------------+--------------------------+ +// | Name: uid | Name: name | Name: fields | +// | Labels: | Labels: | Labels: | +// | Type: []string | Type: []string | Type: []json.RawMessage | +// +---------------------------------------------------------+----------------------------------------------+--------------------------+ +// | alerting/testdata_alerts.json | Alerting with TestData | {"hasTemplateVars":true} | +// | all-panels.json | Panel tests - All panels | {"hasTemplateVars":true} | +// | datasource-elasticsearch/elasticsearch_compare.json | Datasource tests - Elasticsearch comparison | {"hasTemplateVars":true} | +// | datasource-elasticsearch/elasticsearch_v7.json | Datasource tests - Elasticsearch v7 | {"hasTemplateVars":true} | +// | datasource-elasticsearch/elasticsearch_v7_filebeat.json | Datasource tests - Elasticsearch v7 Filebeat | {"hasTemplateVars":true} | +// | datasource-influxdb/influxdb-logs.json | Datasource tests - InfluxDB Logs | {} | +// | datasource-influxdb/influxdb-templated.json | Datasource tests - InfluxDB Templated | {"hasTemplateVars":true} | +// | datasource-mssql/mssql_fakedata.json | Datasource tests - MSSQL | {"hasTemplateVars":true} | +// | datasource-mssql/mssql_unittest.json | Datasource tests - MSSQL (unit test) | {"hasTemplateVars":true} | +// | ... | ... | ... | +// +---------------------------------------------------------+----------------------------------------------+--------------------------+ +// +// +// ๐ŸŒŸ This was machine generated. Do not edit. ๐ŸŒŸ +{ + "frames": [ + { + "schema": { + "name": "summary", + "fields": [ + { + "name": "uid", + "type": "string", + "typeInfo": { + "frame": "string" + } + }, + { + "name": "name", + "type": "string", + "typeInfo": { + "frame": "string" + } + }, + { + "name": "fields", + "type": "other", + "typeInfo": { + "frame": "json.RawMessage" + } + } + ] + }, + "data": { + "values": [ + [ + "alerting/testdata_alerts.json", + "all-panels.json", + "datasource-elasticsearch/elasticsearch_compare.json", + "datasource-elasticsearch/elasticsearch_v7.json", + "datasource-elasticsearch/elasticsearch_v7_filebeat.json", + "datasource-influxdb/influxdb-logs.json", + "datasource-influxdb/influxdb-templated.json", + "datasource-mssql/mssql_fakedata.json", + "datasource-mssql/mssql_unittest.json", + "datasource-mysql/mysql_fakedata.json", + "datasource-mysql/mysql_unittest.json", + "datasource-opentsdb/opentsdb.json", + "datasource-opentsdb/opentsdb_v2.3.json", + "datasource-postgres/postgres_fakedata.json", + "datasource-postgres/postgres_unittest.json", + "datasource-testdata/bar-gauge-demo2.json", + "datasource-testdata/demo1.json", + "datasource-testdata/new_features_in_v62.json", + "datasource-testdata/new_features_in_v74.json", + "datasource-testdata/new_features_in_v8.json", + "e2e-repeats/Repeating-Kitchen-Sink.json", + "e2e-repeats/Repeating-a-panel-horizontally.json", + "e2e-repeats/Repeating-a-panel-vertically.json", + "e2e-repeats/Repeating-a-row-with-a-non-repeating-panel-and-horizontal-repeating-panel.json", + "e2e-repeats/Repeating-a-row-with-a-non-repeating-panel-and-vertical-repeating-panel.json", + "e2e-repeats/Repeating-a-row-with-a-non-repeating-panel.json", + "e2e-repeats/Repeating-a-row-with-a-repeating-horizontal-panel.json", + "e2e-repeats/Repeating-a-row-with-a-repeating-vertical-panel.json", + "e2e-repeats/Repeating-an-empty-row.json", + "feature-templating/global-variables-and-interpolation.json", + "feature-templating/templating-dashboard-links-and-variables.json", + "feature-templating/templating-textbox-e2e-scenarios.json", + "feature-templating/testdata-datalinks.json", + "feature-templating/testdata-nested-variables-drilldown.json", + "feature-templating/testdata-nested-variables.json", + "feature-templating/testdata-repeating.json", + "feature-templating/testdata-test-variable-output.json", + "feature-templating/testdata-variables-textbox.json", + "feature-templating/testdata-variables-that-update-on-time-change.json", + "home.json", + "panel-barchart/barchart-autosizing.json", + "panel-bargauge/bar_gauge_demo.json", + "panel-bargauge/panel_tests_bar_gauge.json", + "panel-bargauge/panel_tests_bar_gauge2.json", + "panel-candlestick/candlestick.json", + "panel-common/auto_decimals.json", + "panel-common/color_modes.json", + "panel-common/lazy_loading.json", + "panel-common/linked-viz.json", + "panel-common/panels_without_title.json", + "panel-common/shared_queries.json", + "panel-gauge/gauge-multi-series.json", + "panel-gauge/gauge_tests.json", + "panel-geomap/geomap-9.1.json", + "panel-geomap/geomap-color-field.json", + "panel-geomap/geomap-spatial-operations-transformer.json", + "panel-geomap/geomap_multi-layers.json", + "panel-geomap/panel-geomap.json", + "panel-graph/graph-gradient-area-fills.json", + "panel-graph/graph-ng-by-value-color-schemes.json", + "panel-graph/graph-ng-gradient-area.json", + "panel-graph/graph-ng-hue-gradients.json", + "panel-graph/graph-ng-nulls.json", + "panel-graph/graph-ng-soft-limits.json", + "panel-graph/graph-ng-stacking.json", + "panel-graph/graph-ng-stacking2.json", + "panel-graph/graph-ng-thresholds.json", + "panel-graph/graph-ng-time.json", + "panel-graph/graph-ng-y-ticks-zero-decimals.json", + "panel-graph/graph-ng-yaxis-ticks.json", + "panel-graph/graph-ng.json", + "panel-graph/graph-shared-tooltip-cursor-position.json", + "panel-graph/graph-shared-tooltips.json", + "panel-graph/graph-time-regions.json", + "panel-graph/graph_tests.json", + "panel-graph/graph_y_axis.json", + "panel-heatmap/heatmap-calculate-log.json", + "panel-heatmap/heatmap-legacy.json", + "panel-histogram/histogram_tests.json", + "panel-library/panel-library.json", + "panel-piechart/panel_test_piechart.json", + "panel-polystat/polystat_test.json", + "panel-stat/panel-stat-tests.json", + "panel-table/table_pagination.json", + "panel-table/table_tests.json", + "panel-table/table_tests_new.json", + "panel-text/text-options.json", + "panel-timeline/timeline-demo.json", + "panel-timeline/timeline-modes.json", + "scenarios/slow_queries_and_annotations.json", + "scenarios/time_zone_support.json", + "transforms/config-from-query.json", + "transforms/join-by-field.json", + "transforms/join-by-labels.json", + "transforms/reuse.json", + "transforms/rows-to-fields.json" + ], + [ + "Alerting with TestData", + "Panel tests - All panels", + "Datasource tests - Elasticsearch comparison", + "Datasource tests - Elasticsearch v7", + "Datasource tests - Elasticsearch v7 Filebeat", + "Datasource tests - InfluxDB Logs", + "Datasource tests - InfluxDB Templated", + "Datasource tests - MSSQL", + "Datasource tests - MSSQL (unit test)", + "Datasource tests - MySQL", + "Datasource tests - MySQL (unittest)", + "Datasource tests - OpenTSDB", + "Datasource tests - OpenTSDB v2.3", + "Datasource tests - Postgres", + "Datasource tests - Postgres (unittest)", + "Bar Gauge Demo Unfilled", + "TestData - Demo Dashboard", + "New Features in v6.2", + "New Features in v7.4", + "New Features in v8.0", + "Repeating Kitchen Sink", + "Repeating a panel horizontally", + "Repeating a panel vertically", + "Repeating a row with a non-repeating panel and horizontal repeating panel", + "Repeating a row with a non-repeating panel and vertical repeating panel", + "Repeating a row with a non-repeating panel", + "Repeating a row with a repeating horizontal panel", + "Repeating a row with a repeating vertical panel", + "Repeating an empty row", + "Templating - Global variables and interpolation", + "Templating - Dashboard Links and Variables", + "Templating - Textbox e2e scenarios", + "Datalinks - variables", + "Templating - Nested Variables Drilldown", + "Templating - Nested Template Variables", + "TestData Repeating Panels", + "Test variable output", + "Templating - Textbox \u0026 data links", + "Templating - Variables That Refresh On Time Change", + "Grafana Dev Overview \u0026 Home", + "BarChart - Panel Tests - Value sizing", + "Bar Gauge Demo", + "Panel Tests - Bar Gauge", + "Panel Tests - Bar Gauge 2", + "Candlestick", + "Panel Tests - Auto Decimals", + "Gradient Color modes", + "Lazy Loading", + "Panel \u0026 data links in stat, gauge and bargauge", + "Panel Tests - With \u0026 Without title", + "Datasource tests - Shared Queries", + "Panel Tests - Gauge Multi Series", + "Panel Tests - Gauge", + "Panel Tests - Geomap 9.1", + "Geomap - color field Copy", + "Panel Tests - Geomap geohash transformer", + "Panel Tests - Geomap Multi Layers", + "Panel Tests - Geomap", + "Panel Tests - Graph - Gradient Area Fills", + "Panel Tests - Graph NG - By value color schemes", + "Panel Tests - Graph NG - Gradient Area Fills", + "Panel Tests - GraphNG - Hue Gradients", + "Panel Tests - Graph NG - Gaps and Connected", + "Panel Tests - Graph NG - softMin/softMax", + "Panel Tests - TimeSeries - stacking", + "TimeSeries \u0026 BarChart Stacking", + "Panel Tests - GraphNG Thresholds", + "Panel Tests - GraphNG - Time Axis", + "Zero Decimals Y Ticks", + "Panel Tests - Graph NG - Y axis ticks", + "Panel Tests - Graph NG", + "Panel Tests - shared tooltips cursor positioning", + "Panel Tests - shared tooltips", + "Panel Tests - Graph Time Regions", + "Panel Tests - Graph", + "Panel Tests - Graph - Y axis ticks", + "Heatmap calculate (log)", + "Legacy heatmap", + "Panel Tests - Histogram", + "Panel - Panel Library", + "Panel Tests - Pie chart", + "Panel Tests - Polystat", + "Panel Tests - Stat", + "Table panel - Pagination", + "Panel Tests - Table", + "Panel Tests - React Table", + "Text options", + "Timeline Demo", + "Timeline Modes", + "Panel tests - Slow Queries \u0026 Annotations", + "Panel Tests - Time zone support", + "Transforms - Config from query", + "Join by field", + "Join by labels", + "Reuse dashboard queries", + "Transforms - Rows to fields" + ], + [ + { + "hasTemplateVars": true + }, + { + "hasTemplateVars": true + }, + { + "hasTemplateVars": true + }, + { + "hasTemplateVars": true + }, + { + "hasTemplateVars": true + }, + {}, + { + "hasTemplateVars": true + }, + { + "hasTemplateVars": true + }, + { + "hasTemplateVars": true + }, + { + "hasTemplateVars": true + }, + { + "hasTemplateVars": true + }, + {}, + {}, + { + "hasTemplateVars": true + }, + { + "hasTemplateVars": true + }, + {}, + {}, + {}, + {}, + {}, + { + "hasTemplateVars": true + }, + { + "hasTemplateVars": true + }, + { + "hasTemplateVars": true + }, + { + "hasTemplateVars": true + }, + { + "hasTemplateVars": true + }, + { + "hasTemplateVars": true + }, + { + "hasTemplateVars": true + }, + { + "hasTemplateVars": true + }, + { + "hasTemplateVars": true + }, + { + "hasTemplateVars": true + }, + { + "hasTemplateVars": true + }, + { + "hasTemplateVars": true + }, + { + "hasTemplateVars": true + }, + { + "hasTemplateVars": true + }, + { + "hasTemplateVars": true + }, + { + "hasTemplateVars": true + }, + {}, + { + "hasTemplateVars": true + }, + { + "hasTemplateVars": true + }, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + { + "hasTemplateVars": true + }, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + { + "hasTemplateVars": true + }, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {} + ] + ] + } + } + ] +} \ No newline at end of file diff --git a/pkg/services/searchV2/testdata/allowed_actions_scope_all.golden.jsonc b/pkg/services/searchV2/testdata/allowed_actions_scope_all.golden.jsonc index 09c22c5b4d9..921960559b8 100644 --- a/pkg/services/searchV2/testdata/allowed_actions_scope_all.golden.jsonc +++ b/pkg/services/searchV2/testdata/allowed_actions_scope_all.golden.jsonc @@ -16,26 +16,26 @@ // } // Name: Query results // Dimensions: 9 Fields by 4 Rows -// +----------------+----------------+-------------------------+------------------+--------------------------------------+--------------------------+---------------------------+----------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -// | Name: kind | Name: uid | Name: name | Name: panel_type | Name: url | Name: tags | Name: ds_uid | Name: location | Name: allowed_actions | -// | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | -// | Type: []string | Type: []string | Type: []string | Type: []string | Type: []string | Type: []*json.RawMessage | Type: []json.RawMessage | Type: []string | Type: []json.RawMessage | -// +----------------+----------------+-------------------------+------------------+--------------------------------------+--------------------------+---------------------------+----------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -// | folder | ujaM1h6nz | abc2 | | /dashboards/f/ujaM1h6nz/abc2 | null | [] | | [{"kind":"folder","uid":"ujaM1h6nz","actions":["folders.permissions:read","folders.permissions:write","folders:create","folders:delete","folders:read","folders:write"]}] | -// | dashboard | 7MeksYbmk | Alerting with TestData | | /d/7MeksYbmk/alerting-with-testdata | [ | [ | yboVMzb7z | [{"kind":"dashboard","uid":"7MeksYbmk","actions":["dashboards.permissions:read","dashboards.permissions:write","dashboards:create","dashboards:delete","dashboards:read","dashboards:write"]},{"kind":"datasource","uid":"datasource-1","actions":["datasources.id:read","datasources.permissions:read","datasources.permissions:write","datasources:delete","datasources:explore","datasources:query","datasources:read","datasources:write"]}] | -// | | | | | | "gdev", | "datasource-1" | | | -// | | | | | | "alerting" | ] | | | -// | | | | | | ] | | | | -// | dashboard | vmie2cmWz | Bar Gauge Demo | | /d/vmie2cmWz/bar-gauge-demo | [ | [ | yboVMzb7z | [{"kind":"dashboard","uid":"vmie2cmWz","actions":["dashboards.permissions:read","dashboards.permissions:write","dashboards:create","dashboards:delete","dashboards:read","dashboards:write"]},{"kind":"datasource","uid":"datasource-2","actions":["datasources.id:read","datasources.permissions:read","datasources.permissions:write","datasources:delete","datasources:explore","datasources:query","datasources:read","datasources:write"]},{"kind":"datasource","uid":"datasource-3","actions":["datasources.id:read","datasources.permissions:read","datasources.permissions:write","datasources:delete","datasources:explore","datasources:query","datasources:read","datasources:write"]},{"kind":"datasource","uid":"datasource-4","actions":["datasources.id:read","datasources.permissions:read","datasources.permissions:write","datasources:delete","datasources:explore","datasources:query","datasources:read","datasources:write"]}] | -// | | | | | | "gdev", | "datasource-2", | | | -// | | | | | | "demo" | "datasource-3", | | | -// | | | | | | ] | "datasource-4" | | | -// | | | | | | | ] | | | -// | dashboard | xMsQdBfWz | Bar Gauge Demo Unfilled | | /d/xMsQdBfWz/bar-gauge-demo-unfilled | [ | [] | yboVMzb7z | [{"kind":"dashboard","uid":"xMsQdBfWz","actions":["dashboards.permissions:read","dashboards.permissions:write","dashboards:create","dashboards:delete","dashboards:read","dashboards:write"]}] | -// | | | | | | "gdev", | | | | -// | | | | | | "demo" | | | | -// | | | | | | ] | | | | -// +----------------+----------------+-------------------------+------------------+--------------------------------------+--------------------------+---------------------------+----------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +// +----------------+----------------+-------------------------+------------------+--------------------------------------+--------------------------+---------------------------+----------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +// | Name: kind | Name: uid | Name: name | Name: panel_type | Name: url | Name: tags | Name: ds_uid | Name: location | Name: allowed_actions | +// | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | +// | Type: []string | Type: []string | Type: []string | Type: []string | Type: []string | Type: []*json.RawMessage | Type: []json.RawMessage | Type: []string | Type: []json.RawMessage | +// +----------------+----------------+-------------------------+------------------+--------------------------------------+--------------------------+---------------------------+----------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +// | folder | ujaM1h6nz | abc2 | | /dashboards/f/ujaM1h6nz/abc2 | null | [] | | [{"kind":"folder","uid":"ujaM1h6nz","actions":["folders.permissions:read","folders.permissions:write","folders:create","folders:delete","folders:read","folders:write"]}] | +// | dashboard | 7MeksYbmk | Alerting with TestData | | /d/7MeksYbmk/alerting-with-testdata | [ | [ | yboVMzb7z | [{"kind":"dashboard","uid":"7MeksYbmk","actions":["dashboards.permissions:read","dashboards.permissions:write","dashboards:create","dashboards:delete","dashboards:read","dashboards:write"]},{"kind":"ds","uid":"datasource-1","actions":["datasources.id:read","datasources.permissions:read","datasources.permissions:write","datasources:delete","datasources:explore","datasources:query","datasources:read","datasources:write"]}] | +// | | | | | | "gdev", | "datasource-1" | | | +// | | | | | | "alerting" | ] | | | +// | | | | | | ] | | | | +// | dashboard | vmie2cmWz | Bar Gauge Demo | | /d/vmie2cmWz/bar-gauge-demo | [ | [ | yboVMzb7z | [{"kind":"dashboard","uid":"vmie2cmWz","actions":["dashboards.permissions:read","dashboards.permissions:write","dashboards:create","dashboards:delete","dashboards:read","dashboards:write"]},{"kind":"ds","uid":"datasource-2","actions":["datasources.id:read","datasources.permissions:read","datasources.permissions:write","datasources:delete","datasources:explore","datasources:query","datasources:read","datasources:write"]},{"kind":"ds","uid":"datasource-3","actions":["datasources.id:read","datasources.permissions:read","datasources.permissions:write","datasources:delete","datasources:explore","datasources:query","datasources:read","datasources:write"]},{"kind":"ds","uid":"datasource-4","actions":["datasources.id:read","datasources.permissions:read","datasources.permissions:write","datasources:delete","datasources:explore","datasources:query","datasources:read","datasources:write"]}] | +// | | | | | | "gdev", | "datasource-2", | | | +// | | | | | | "demo" | "datasource-3", | | | +// | | | | | | ] | "datasource-4" | | | +// | | | | | | | ] | | | +// | dashboard | xMsQdBfWz | Bar Gauge Demo Unfilled | | /d/xMsQdBfWz/bar-gauge-demo-unfilled | [ | [] | yboVMzb7z | [{"kind":"dashboard","uid":"xMsQdBfWz","actions":["dashboards.permissions:read","dashboards.permissions:write","dashboards:create","dashboards:delete","dashboards:read","dashboards:write"]}] | +// | | | | | | "gdev", | | | | +// | | | | | | "demo" | | | | +// | | | | | | ] | | | | +// +----------------+----------------+-------------------------+------------------+--------------------------------------+--------------------------+---------------------------+----------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ // // // ๐ŸŒŸ This was machine generated. Do not edit. ๐ŸŒŸ @@ -228,7 +228,7 @@ ] }, { - "kind": "datasource", + "kind": "ds", "uid": "datasource-1", "actions": [ "datasources.id:read", @@ -256,7 +256,7 @@ ] }, { - "kind": "datasource", + "kind": "ds", "uid": "datasource-2", "actions": [ "datasources.id:read", @@ -270,7 +270,7 @@ ] }, { - "kind": "datasource", + "kind": "ds", "uid": "datasource-3", "actions": [ "datasources.id:read", @@ -284,7 +284,7 @@ ] }, { - "kind": "datasource", + "kind": "ds", "uid": "datasource-4", "actions": [ "datasources.id:read", diff --git a/pkg/services/searchV2/testdata/allowed_actions_scope_uids.golden.jsonc b/pkg/services/searchV2/testdata/allowed_actions_scope_uids.golden.jsonc index 3f6cbb68260..de9186f56b9 100644 --- a/pkg/services/searchV2/testdata/allowed_actions_scope_uids.golden.jsonc +++ b/pkg/services/searchV2/testdata/allowed_actions_scope_uids.golden.jsonc @@ -16,26 +16,26 @@ // } // Name: Query results // Dimensions: 9 Fields by 4 Rows -// +----------------+----------------+-------------------------+------------------+--------------------------------------+--------------------------+---------------------------+----------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -// | Name: kind | Name: uid | Name: name | Name: panel_type | Name: url | Name: tags | Name: ds_uid | Name: location | Name: allowed_actions | -// | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | -// | Type: []string | Type: []string | Type: []string | Type: []string | Type: []string | Type: []*json.RawMessage | Type: []json.RawMessage | Type: []string | Type: []json.RawMessage | -// +----------------+----------------+-------------------------+------------------+--------------------------------------+--------------------------+---------------------------+----------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -// | folder | ujaM1h6nz | abc2 | | /dashboards/f/ujaM1h6nz/abc2 | null | [] | | [{"kind":"folder","uid":"ujaM1h6nz","actions":["folders:read"]}] | -// | dashboard | 7MeksYbmk | Alerting with TestData | | /d/7MeksYbmk/alerting-with-testdata | [ | [ | yboVMzb7z | [{"kind":"dashboard","uid":"7MeksYbmk","actions":["dashboards:write"]},{"kind":"datasource","uid":"datasource-1","actions":[]}] | -// | | | | | | "gdev", | "datasource-1" | | | -// | | | | | | "alerting" | ] | | | -// | | | | | | ] | | | | -// | dashboard | vmie2cmWz | Bar Gauge Demo | | /d/vmie2cmWz/bar-gauge-demo | [ | [ | yboVMzb7z | [{"kind":"dashboard","uid":"vmie2cmWz","actions":[]},{"kind":"datasource","uid":"datasource-2","actions":["datasources:read"]},{"kind":"datasource","uid":"datasource-3","actions":["datasources:read"]},{"kind":"datasource","uid":"datasource-4","actions":[]}] | -// | | | | | | "gdev", | "datasource-2", | | | -// | | | | | | "demo" | "datasource-3", | | | -// | | | | | | ] | "datasource-4" | | | -// | | | | | | | ] | | | -// | dashboard | xMsQdBfWz | Bar Gauge Demo Unfilled | | /d/xMsQdBfWz/bar-gauge-demo-unfilled | [ | [] | yboVMzb7z | [{"kind":"dashboard","uid":"xMsQdBfWz","actions":[]}] | -// | | | | | | "gdev", | | | | -// | | | | | | "demo" | | | | -// | | | | | | ] | | | | -// +----------------+----------------+-------------------------+------------------+--------------------------------------+--------------------------+---------------------------+----------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +// +----------------+----------------+-------------------------+------------------+--------------------------------------+--------------------------+---------------------------+----------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +// | Name: kind | Name: uid | Name: name | Name: panel_type | Name: url | Name: tags | Name: ds_uid | Name: location | Name: allowed_actions | +// | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | +// | Type: []string | Type: []string | Type: []string | Type: []string | Type: []string | Type: []*json.RawMessage | Type: []json.RawMessage | Type: []string | Type: []json.RawMessage | +// +----------------+----------------+-------------------------+------------------+--------------------------------------+--------------------------+---------------------------+----------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +// | folder | ujaM1h6nz | abc2 | | /dashboards/f/ujaM1h6nz/abc2 | null | [] | | [{"kind":"folder","uid":"ujaM1h6nz","actions":["folders:read"]}] | +// | dashboard | 7MeksYbmk | Alerting with TestData | | /d/7MeksYbmk/alerting-with-testdata | [ | [ | yboVMzb7z | [{"kind":"dashboard","uid":"7MeksYbmk","actions":["dashboards:write"]},{"kind":"ds","uid":"datasource-1","actions":[]}] | +// | | | | | | "gdev", | "datasource-1" | | | +// | | | | | | "alerting" | ] | | | +// | | | | | | ] | | | | +// | dashboard | vmie2cmWz | Bar Gauge Demo | | /d/vmie2cmWz/bar-gauge-demo | [ | [ | yboVMzb7z | [{"kind":"dashboard","uid":"vmie2cmWz","actions":[]},{"kind":"ds","uid":"datasource-2","actions":["datasources:read"]},{"kind":"ds","uid":"datasource-3","actions":["datasources:read"]},{"kind":"ds","uid":"datasource-4","actions":[]}] | +// | | | | | | "gdev", | "datasource-2", | | | +// | | | | | | "demo" | "datasource-3", | | | +// | | | | | | ] | "datasource-4" | | | +// | | | | | | | ] | | | +// | dashboard | xMsQdBfWz | Bar Gauge Demo Unfilled | | /d/xMsQdBfWz/bar-gauge-demo-unfilled | [ | [] | yboVMzb7z | [{"kind":"dashboard","uid":"xMsQdBfWz","actions":[]}] | +// | | | | | | "gdev", | | | | +// | | | | | | "demo" | | | | +// | | | | | | ] | | | | +// +----------------+----------------+-------------------------+------------------+--------------------------------------+--------------------------+---------------------------+----------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ // // // ๐ŸŒŸ This was machine generated. Do not edit. ๐ŸŒŸ @@ -218,7 +218,7 @@ ] }, { - "kind": "datasource", + "kind": "ds", "uid": "datasource-1", "actions": [] } @@ -230,21 +230,21 @@ "actions": [] }, { - "kind": "datasource", + "kind": "ds", "uid": "datasource-2", "actions": [ "datasources:read" ] }, { - "kind": "datasource", + "kind": "ds", "uid": "datasource-3", "actions": [ "datasources:read" ] }, { - "kind": "datasource", + "kind": "ds", "uid": "datasource-4", "actions": [] } diff --git a/pkg/services/store/object/kind.go b/pkg/services/store/object/kind.go new file mode 100644 index 00000000000..6b57250b315 --- /dev/null +++ b/pkg/services/store/object/kind.go @@ -0,0 +1,10 @@ +package object + +// NOTE this is just a temporary registry/list so we can use constants +// TODO replace with codegen from kind schema system + +const StandardKindDashboard = "dashboard" +const StandardKindFolder = "folder" +const StandardKindPanel = "panel" // types: heatmap, timeseries, table, ... +const StandardKindDataSource = "ds" // types: influx, prometheus, test, ... +const StandardKindTransform = "transform" // types: joinByField, pivot, organizeFields, ... diff --git a/pkg/services/store/object/object.go b/pkg/services/store/object/object.go new file mode 100644 index 00000000000..089bc838f95 --- /dev/null +++ b/pkg/services/store/object/object.go @@ -0,0 +1,65 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.28.1 +// protoc v3.21.5 +// source: object.proto + +package object + + +// Will be replaced with something from the SDK +type UserInfo struct { + Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` // internal grafana ID + Login string `protobuf:"bytes,2,opt,name=login,proto3" json:"login,omitempty"` // string ID? +} + +// The canonical object/document data -- this represents the raw bytes and storage level metadata +type RawObject struct { + // Unique ID + UID string `protobuf:"bytes,1,opt,name=UID,proto3" json:"UID,omitempty"` + // Identify the object kind. This kind will be used to apply a schema to the body and + // will trigger additional indexing behavior. + Kind string `protobuf:"bytes,2,opt,name=kind,proto3" json:"kind,omitempty"` + // Time in epoch milliseconds that the object was modified + Modified int64 `protobuf:"varint,3,opt,name=modified,proto3" json:"modified,omitempty"` + // Who modified the object + ModifiedBy *UserInfo `protobuf:"bytes,4,opt,name=modified_by,json=modifiedBy,proto3" json:"modified_by,omitempty"` + // Content Length + Size int64 `protobuf:"varint,5,opt,name=size,proto3" json:"size,omitempty"` + // MD5 digest of the body + ETag string `protobuf:"bytes,6,opt,name=ETag,proto3" json:"ETag,omitempty"` + // Raw bytes of the storage object. The kind will determine what is a valid payload + Body []byte `protobuf:"bytes,7,opt,name=body,proto3" json:"body,omitempty"` + // The version will change when the object is saved. It is not necessarily sortable + // + // NOTE: currently managed by the dashboard+dashboard_version tables + Version string `protobuf:"bytes,8,opt,name=version,proto3" json:"version,omitempty"` + // optional "save" or "commit" message + // + // NOTE: currently managed by the dashboard_version table, and will be returned from a "history" command + Comment string `protobuf:"bytes,9,opt,name=comment,proto3" json:"comment,omitempty"` + // Location (path/repo/etc) that defines the canonocal form + // + // NOTE: currently managed by the dashboard_provisioning table + SyncSrc string `protobuf:"bytes,10,opt,name=sync_src,json=syncSrc,proto3" json:"sync_src,omitempty"` + // Time in epoch milliseconds that the object was last synced with an external system (provisioning/git) + // + // NOTE: currently managed by the dashboard_provisioning table + SyncTime int64 `protobuf:"varint,11,opt,name=sync_time,json=syncTime,proto3" json:"sync_time,omitempty"` +} + +// Searchable fields extracted from the object +type ObjectErrorInfo struct { + Code int64 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` // TODO... registry somewhere... should be limited to most severe issues + Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"` + Details string `protobuf:"bytes,3,opt,name=details,proto3" json:"details,omitempty"` +} + +type ExternalReference struct { + // datasource, panel + Kind string `protobuf:"bytes,1,opt,name=kind,proto3" json:"kind,omitempty"` + // prometheus / heatmap + Type string `protobuf:"bytes,2,opt,name=type,proto3" json:"type,omitempty"` + // Unique ID for this object + UID string `protobuf:"bytes,3,opt,name=UID,proto3" json:"UID,omitempty"` +} diff --git a/pkg/services/store/object/reference.go b/pkg/services/store/object/reference.go new file mode 100644 index 00000000000..217e2008a08 --- /dev/null +++ b/pkg/services/store/object/reference.go @@ -0,0 +1,51 @@ +package object + +import ( + "fmt" + "sort" +) + +// A reference accumulator can combine +type ReferenceAccumulator interface { + // Add references as we find them + Add(kind string, subtype string, uid string) + + // Returns the set of distinct references in a sorted order + Get() []*ExternalReference +} + +func NewReferenceAccumulator() ReferenceAccumulator { + return &referenceAccumulator{ + refs: make(map[string]*ExternalReference), + } +} + +type referenceAccumulator struct { + refs map[string]*ExternalReference +} + +func (x *referenceAccumulator) Add(kind string, sub string, uid string) { + key := fmt.Sprintf("%s/%s/%s", kind, sub, uid) + _, ok := x.refs[key] + if !ok { + x.refs[key] = &ExternalReference{ + Kind: kind, + Type: sub, + UID: uid, + } + } +} + +func (x *referenceAccumulator) Get() []*ExternalReference { + keys := make([]string, 0, len(x.refs)) + for k := range x.refs { + keys = append(keys, k) + } + sort.Strings(keys) + + refs := make([]*ExternalReference, len(keys)) + for i, key := range keys { + refs[i] = x.refs[key] + } + return refs +} diff --git a/pkg/services/store/object/summary.go b/pkg/services/store/object/summary.go new file mode 100644 index 00000000000..895e469237d --- /dev/null +++ b/pkg/services/store/object/summary.go @@ -0,0 +1,29 @@ +package object + +// ObjectSummary is derived from a RawObject and should not depend on system state +// The summary is used for a unified search and listings objects since the fully +type ObjectSummary struct { + UID string `json:"uid,omitempty"` + Kind string `json:"kind,omitempty"` + Name string `json:"name,omitempty"` + Description string `json:"description,omitempty"` + Labels map[string]string `json:"labels,omitempty"` // "tags" are represented as keys with empty values + URL string `json:"URL,omitempty"` // not great to save here, but maybe not terrible :shrug: + Error *ObjectErrorInfo `json:"error,omitempty"` + + // Optional values -- schema will define the type + Fields map[string]interface{} `json:"fields,omitempty"` // Saved as JSON, returned in results, but values not sortable + + // eg: panels within dashboard + Nested []*ObjectSummary `json:"nested,omitempty"` + + // Optional references to external things + References []*ExternalReference `json:"references,omitempty"` + + // struct can not be extended + _ interface{} +} + +// ObjectSummaryBuilder will read an object and create the summary. +// This should not include values that depend on system state, only the raw object +type ObjectSummaryBuilder = func(obj *RawObject) (ObjectSummary, error)