diff --git a/apps/advisor/go.sum b/apps/advisor/go.sum index 142646a8543..79aea07d576 100644 --- a/apps/advisor/go.sum +++ b/apps/advisor/go.sum @@ -130,9 +130,6 @@ github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8 github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/ProtonMail/go-crypto v1.1.6 h1:ZcV+Ropw6Qn0AX9brlQLAUXfqLBc7Bl+f/DmNxpLfdw= github.com/ProtonMail/go-crypto v1.1.6/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE= -github.com/RoaringBitmap/roaring v1.9.3 h1:t4EbC5qQwnisr5PrP9nt0IRhRTb9gMUgQF4t4S2OByM= -github.com/RoaringBitmap/roaring/v2 v2.4.5 h1:uGrrMreGjvAtTBobc0g5IrW1D5ldxDQYe2JW2gggRdg= -github.com/RoaringBitmap/roaring/v2 v2.4.5/go.mod h1:FiJcsfkGje/nZBZgCu0ZxCPOKD/hVXDS2dXi7/eUFE0= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/VividCortex/mysqlerr v0.0.0-20170204212430-6c6b55f8796f h1:HR5nRmUQgXrwqZOwZ2DAc/aCi3Bu3xENpspW935vxu0= @@ -222,48 +219,10 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k= -github.com/bits-and-blooms/bitset v1.22.0 h1:Tquv9S8+SGaS3EhyA+up3FXzmkhxPGjQQCkcs2uw7w4= -github.com/bits-and-blooms/bitset v1.22.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= -github.com/blevesearch/bleve/v2 v2.5.0 h1:HzYqBy/5/M9Ul9ESEmXzN/3Jl7YpmWBdHM/+zzv/3k4= -github.com/blevesearch/bleve/v2 v2.5.0/go.mod h1:PcJzTPnEynO15dCf9isxOga7YFRa/cMSsbnRwnszXUk= -github.com/blevesearch/bleve_index_api v1.2.7 h1:c8r9vmbaYQroAMSGag7zq5gEVPiuXrUQDqfnj7uYZSY= -github.com/blevesearch/bleve_index_api v1.2.7/go.mod h1:rKQDl4u51uwafZxFrPD1R7xFOwKnzZW7s/LSeK4lgo0= -github.com/blevesearch/geo v0.1.20 h1:paaSpu2Ewh/tn5DKn/FB5SzvH0EWupxHEIwbCk/QPqM= -github.com/blevesearch/geo v0.1.20/go.mod h1:DVG2QjwHNMFmjo+ZgzrIq2sfCh6rIHzy9d9d0B59I6w= -github.com/blevesearch/go-faiss v1.0.25 h1:lel1rkOUGbT1CJ0YgzKwC7k+XH0XVBHnCVWahdCXk4U= -github.com/blevesearch/go-faiss v1.0.25/go.mod h1:OMGQwOaRRYxrmeNdMrXJPvVx8gBnvE5RYrr0BahNnkk= -github.com/blevesearch/go-porterstemmer v1.0.3 h1:GtmsqID0aZdCSNiY8SkuPJ12pD4jI+DdXTAn4YRcHCo= -github.com/blevesearch/go-porterstemmer v1.0.3/go.mod h1:angGc5Ht+k2xhJdZi511LtmxuEf0OVpvUUNrwmM1P7M= -github.com/blevesearch/gtreap v0.1.1 h1:2JWigFrzDMR+42WGIN/V2p0cUvn4UP3C4Q5nmaZGW8Y= -github.com/blevesearch/gtreap v0.1.1/go.mod h1:QaQyDRAT51sotthUWAH4Sj08awFSSWzgYICSZ3w0tYk= -github.com/blevesearch/mmap-go v1.0.4 h1:OVhDhT5B/M1HNPpYPBKIEJaD0F3Si+CrEKULGCDPWmc= -github.com/blevesearch/mmap-go v1.0.4/go.mod h1:EWmEAOmdAS9z/pi/+Toxu99DnsbhG1TIxUoRmJw/pSs= -github.com/blevesearch/scorch_segment_api/v2 v2.3.9 h1:X6nJXnNHl7nasXW+U6y2Ns2Aw8F9STszkYkyBfQ+p0o= -github.com/blevesearch/scorch_segment_api/v2 v2.3.9/go.mod h1:IrzspZlVjhf4X29oJiEhBxEteTqOY9RlYlk1lCmYHr4= -github.com/blevesearch/segment v0.9.1 h1:+dThDy+Lvgj5JMxhmOVlgFfkUtZV2kw49xax4+jTfSU= -github.com/blevesearch/segment v0.9.1/go.mod h1:zN21iLm7+GnBHWTao9I+Au/7MBiL8pPFtJBJTsk6kQw= -github.com/blevesearch/snowballstem v0.9.0 h1:lMQ189YspGP6sXvZQ4WZ+MLawfV8wOmPoD/iWeNXm8s= -github.com/blevesearch/snowballstem v0.9.0/go.mod h1:PivSj3JMc8WuaFkTSRDW2SlrulNWPl4ABg1tC/hlgLs= -github.com/blevesearch/upsidedown_store_api v1.0.2 h1:U53Q6YoWEARVLd1OYNc9kvhBMGZzVrdmaozG2MfoB+A= -github.com/blevesearch/upsidedown_store_api v1.0.2/go.mod h1:M01mh3Gpfy56Ps/UXHjEO/knbqyQ1Oamg8If49gRwrQ= -github.com/blevesearch/vellum v1.1.0 h1:CinkGyIsgVlYf8Y2LUQHvdelgXr6PYuvoDIajq6yR9w= -github.com/blevesearch/vellum v1.1.0/go.mod h1:QgwWryE8ThtNPxtgWJof5ndPfx0/YMBh+W2weHKPw8Y= -github.com/blevesearch/zapx/v11 v11.4.1 h1:qFCPlFbsEdwbbckJkysptSQOsHn4s6ZOHL5GMAIAVHA= -github.com/blevesearch/zapx/v11 v11.4.1/go.mod h1:qNOGxIqdPC1MXauJCD9HBG487PxviTUUbmChFOAosGs= -github.com/blevesearch/zapx/v12 v12.4.1 h1:K77bhypII60a4v8mwvav7r4IxWA8qxhNjgF9xGdb9eQ= -github.com/blevesearch/zapx/v12 v12.4.1/go.mod h1:QRPrlPOzAxBNMI0MkgdD+xsTqx65zbuPr3Ko4Re49II= -github.com/blevesearch/zapx/v13 v13.4.1 h1:EnkEMZFUK0lsW/jOJJF2xOcp+W8TjEsyeN5BeAZEYYE= -github.com/blevesearch/zapx/v13 v13.4.1/go.mod h1:e6duBMlCvgbH9rkzNMnUa9hRI9F7ri2BRcHfphcmGn8= -github.com/blevesearch/zapx/v14 v14.4.1 h1:G47kGCshknBZzZAtjcnIAMn3oNx8XBLxp8DMq18ogyE= -github.com/blevesearch/zapx/v14 v14.4.1/go.mod h1:O7sDxiaL2r2PnCXbhh1Bvm7b4sP+jp4unE9DDPWGoms= -github.com/blevesearch/zapx/v15 v15.4.1 h1:B5IoTMUCEzFdc9FSQbhVOxAY+BO17c05866fNruiI7g= -github.com/blevesearch/zapx/v15 v15.4.1/go.mod h1:b/MreHjYeQoLjyY2+UaM0hGZZUajEbE0xhnr1A2/Q6Y= -github.com/blevesearch/zapx/v16 v16.2.2 h1:MifKJVRTEhMTgSlle2bDRTb39BGc9jXFRLPZc6r0Rzk= -github.com/blevesearch/zapx/v16 v16.2.2/go.mod h1:B9Pk4G1CqtErgQV9DyCSA9Lb7WZe4olYfGw7fVDZ4sk= github.com/bluele/gcache v0.0.2 h1:WcbfdXICg7G/DGBh1PFfcirkWOQV+v077yF1pSy3DGw= github.com/bluele/gcache v0.0.2/go.mod h1:m15KV+ECjptwSPxKhOhQoAFQVtUFjTVkc3H8o0t/fp0= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= @@ -526,8 +485,6 @@ github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9v github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= github.com/golang-migrate/migrate/v4 v4.7.0 h1:gONcHxHApDTKXDyLH/H97gEHmpu1zcnnbAaq2zgrPrs= github.com/golang-migrate/migrate/v4 v4.7.0/go.mod h1:Qvut3N4xKWjoH3sokBccML6WyHSnggXm/DvMMnTsQIc= -github.com/golang/geo v0.0.0-20210211234256-740aa86cb551 h1:gtexQ/VGyN+VVFRXSFiguSNcXmS6rkKT+X7FdIrTtfo= -github.com/golang/geo v0.0.0-20210211234256-740aa86cb551/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -936,8 +893,6 @@ github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWu github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw= github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= -github.com/mschoch/smat v0.2.0 h1:8imxQsjDm8yFEAVBe7azKmKSgzSkZXDuKkSq9374khM= -github.com/mschoch/smat v0.2.0/go.mod h1:kc9mz7DoBKqDyiRL7VZN8KvXQMWeTaVnttLRXOlotKw= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= @@ -1184,8 +1139,6 @@ github.com/zeebo/errs v1.4.0/go.mod h1:sgbWHsvVuTPHcqJJGQ1WhI5KbWlHYz+2+2C/LSEtC github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0= github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= gitlab.com/nyarla/go-crypt v0.0.0-20160106005555-d9a5dc2b789b/go.mod h1:T3BPAOm2cqquPa0MKWeNkmOM5RQsRhkrwMWonFMN7fE= -go.etcd.io/bbolt v1.4.2 h1:IrUHp260R8c+zYx/Tm8QZr04CX+qWS5PGfPdevhdm1I= -go.etcd.io/bbolt v1.4.2/go.mod h1:Is8rSHO/b4f3XigBC0lL0+4FwAQv3HXEEIgFMuKHceM= go.etcd.io/etcd/api/v3 v3.5.4/go.mod h1:5GB2vv4A4AOn3yk7MftYGHkUfGtDHnEraIjym4dYz5A= go.etcd.io/etcd/api/v3 v3.6.4 h1:7F6N7toCKcV72QmoUKa23yYLiiljMrT4xCeBL9BmXdo= go.etcd.io/etcd/api/v3 v3.6.4/go.mod h1:eFhhvfR8Px1P6SEuLT600v+vrhdDTdcfMzmnxVXXSbk= diff --git a/pkg/registry/apis/dashboard/legacysearcher/search_client.go b/pkg/registry/apis/dashboard/legacysearcher/search_client.go index dde82737e23..9782ce6326d 100644 --- a/pkg/registry/apis/dashboard/legacysearcher/search_client.go +++ b/pkg/registry/apis/dashboard/legacysearcher/search_client.go @@ -23,7 +23,7 @@ import ( "github.com/grafana/grafana/pkg/services/sqlstore/searchstore" "github.com/grafana/grafana/pkg/storage/unified/resource" "github.com/grafana/grafana/pkg/storage/unified/resourcepb" - unisearch "github.com/grafana/grafana/pkg/storage/unified/search" + "github.com/grafana/grafana/pkg/storage/unified/search/builders" ) type DashboardSearchClient struct { @@ -37,11 +37,11 @@ func NewDashboardSearchClient(dashboardStore dashboards.Store, sorter sort.Servi } var sortByMapping = map[string]string{ - unisearch.DASHBOARD_VIEWS_LAST_30_DAYS: "viewed-recently", - unisearch.DASHBOARD_VIEWS_TOTAL: "viewed", - unisearch.DASHBOARD_ERRORS_LAST_30_DAYS: "errors-recently", - unisearch.DASHBOARD_ERRORS_TOTAL: "errors", - "title": "alpha", + builders.DASHBOARD_VIEWS_LAST_30_DAYS: "viewed-recently", + builders.DASHBOARD_VIEWS_TOTAL: "viewed", + builders.DASHBOARD_ERRORS_LAST_30_DAYS: "errors-recently", + builders.DASHBOARD_ERRORS_TOTAL: "errors", + "title": "alpha", } func ParseSortName(sortName string) (string, bool, error) { @@ -231,7 +231,7 @@ func (c *DashboardSearchClient) Search(ctx context.Context, req *resourcepb.Reso } query.ManagerIdentity = vals[0] - case unisearch.DASHBOARD_LIBRARY_PANEL_REFERENCE: + case builders.DASHBOARD_LIBRARY_PANEL_REFERENCE: if len(vals) != 1 { return nil, apierrors.NewBadRequest("only one library panel uid is supported") } diff --git a/pkg/registry/apis/dashboard/legacysearcher/search_client_test.go b/pkg/registry/apis/dashboard/legacysearcher/search_client_test.go index 8f1974bee68..cb7ead459f6 100644 --- a/pkg/registry/apis/dashboard/legacysearcher/search_client_test.go +++ b/pkg/registry/apis/dashboard/legacysearcher/search_client_test.go @@ -19,7 +19,7 @@ import ( "github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/storage/unified/resource" "github.com/grafana/grafana/pkg/storage/unified/resourcepb" - unisearch "github.com/grafana/grafana/pkg/storage/unified/search" + "github.com/grafana/grafana/pkg/storage/unified/search/builders" ) func TestDashboardSearchClient_Search(t *testing.T) { @@ -130,7 +130,7 @@ func TestDashboardSearchClient_Search(t *testing.T) { }, SortBy: []*resourcepb.ResourceSearchRequest_Sort{ { - Field: resource.SEARCH_FIELD_PREFIX + unisearch.DASHBOARD_VIEWS_TOTAL, // "fields." prefix should be removed + Field: resource.SEARCH_FIELD_PREFIX + builders.DASHBOARD_VIEWS_TOTAL, // "fields." prefix should be removed Desc: false, }, }, @@ -195,7 +195,7 @@ func TestDashboardSearchClient_Search(t *testing.T) { }, SortBy: []*resourcepb.ResourceSearchRequest_Sort{ { - Field: unisearch.DASHBOARD_ERRORS_LAST_30_DAYS, + Field: builders.DASHBOARD_ERRORS_LAST_30_DAYS, Desc: true, }, }, @@ -560,7 +560,7 @@ func TestDashboardSearchClient_Search(t *testing.T) { }, SortBy: []*resourcepb.ResourceSearchRequest_Sort{ { - Field: resource.SEARCH_FIELD_PREFIX + unisearch.DASHBOARD_VIEWS_TOTAL, + Field: resource.SEARCH_FIELD_PREFIX + builders.DASHBOARD_VIEWS_TOTAL, }, }, } @@ -591,7 +591,7 @@ func TestDashboardSearchClient_Search(t *testing.T) { Key: dashboardKey, Fields: []*resourcepb.Requirement{ { - Key: unisearch.DASHBOARD_LIBRARY_PANEL_REFERENCE, + Key: builders.DASHBOARD_LIBRARY_PANEL_REFERENCE, Operator: "=", Values: []string{"test-library-panel"}, }, @@ -633,7 +633,7 @@ func TestDashboardSearchClient_Search(t *testing.T) { Key: dashboardKey, Fields: []*resourcepb.Requirement{ { - Key: unisearch.DASHBOARD_LIBRARY_PANEL_REFERENCE, + Key: builders.DASHBOARD_LIBRARY_PANEL_REFERENCE, Operator: "=", Values: []string{"panel1", "panel2"}, }, @@ -652,7 +652,7 @@ func TestDashboardSearchClient_Search(t *testing.T) { Key: dashboardKey, Fields: []*resourcepb.Requirement{ { - Key: unisearch.DASHBOARD_LIBRARY_PANEL_REFERENCE, + Key: builders.DASHBOARD_LIBRARY_PANEL_REFERENCE, Operator: "=", Values: []string{"test-library-panel"}, }, @@ -679,7 +679,7 @@ func TestDashboardSearchClient_Search(t *testing.T) { Key: dashboardKey, Fields: []*resourcepb.Requirement{ { - Key: unisearch.DASHBOARD_LIBRARY_PANEL_REFERENCE, + Key: builders.DASHBOARD_LIBRARY_PANEL_REFERENCE, Operator: "=", Values: []string{"unused-library-panel"}, }, @@ -713,28 +713,28 @@ func TestParseSortName(t *testing.T) { { name: "viewed-recently with desc suffix", sortName: "viewed-recently-desc", - wantField: unisearch.DASHBOARD_VIEWS_LAST_30_DAYS, + wantField: builders.DASHBOARD_VIEWS_LAST_30_DAYS, wantDesc: true, wantErr: false, }, { name: "defaults to desc", sortName: "viewed", - wantField: unisearch.DASHBOARD_VIEWS_TOTAL, + wantField: builders.DASHBOARD_VIEWS_TOTAL, wantDesc: true, wantErr: false, }, { name: "errors-recentlyy with asc suffix", sortName: "errors-recently-asc", - wantField: unisearch.DASHBOARD_ERRORS_LAST_30_DAYS, + wantField: builders.DASHBOARD_ERRORS_LAST_30_DAYS, wantDesc: false, wantErr: false, }, { name: "errors - defaults to desc too", sortName: "errors", - wantField: unisearch.DASHBOARD_ERRORS_TOTAL, + wantField: builders.DASHBOARD_ERRORS_TOTAL, wantDesc: true, wantErr: false, }, diff --git a/pkg/registry/apis/dashboard/search.go b/pkg/registry/apis/dashboard/search.go index 0f1b83a7e18..6d85a66b344 100644 --- a/pkg/registry/apis/dashboard/search.go +++ b/pkg/registry/apis/dashboard/search.go @@ -32,7 +32,7 @@ import ( "github.com/grafana/grafana/pkg/storage/legacysql/dualwrite" "github.com/grafana/grafana/pkg/storage/unified/resource" "github.com/grafana/grafana/pkg/storage/unified/resourcepb" - "github.com/grafana/grafana/pkg/storage/unified/search" + "github.com/grafana/grafana/pkg/storage/unified/search/builders" "github.com/grafana/grafana/pkg/util/errhttp" ) @@ -406,7 +406,7 @@ func convertHttpSearchRequestToResourceSearchRequest(queryParams url.Values, use // Add sorting if queryParams.Has("sort") { for _, sort := range queryParams["sort"] { - if slices.Contains(search.DashboardFields(), sort) { + if slices.Contains(builders.DashboardFields(), sort) { sort = resource.SEARCH_FIELD_PREFIX + sort } s := &resourcepb.ResourceSearchRequest_Sort{Field: sort} @@ -441,7 +441,7 @@ func convertHttpSearchRequestToResourceSearchRequest(queryParams url.Values, use // The libraryPanel filter if libraryPanel, ok := queryParams["libraryPanel"]; ok { searchRequest.Options.Fields = append(searchRequest.Options.Fields, &resourcepb.Requirement{ - Key: search.DASHBOARD_LIBRARY_PANEL_REFERENCE, + Key: builders.DASHBOARD_LIBRARY_PANEL_REFERENCE, Operator: "=", Values: libraryPanel, }) diff --git a/pkg/registry/apis/iam/user/legacy_search.go b/pkg/registry/apis/iam/user/legacy_search.go index 759dc7f55a7..7459e7074e4 100644 --- a/pkg/registry/apis/iam/user/legacy_search.go +++ b/pkg/registry/apis/iam/user/legacy_search.go @@ -12,7 +12,7 @@ import ( "github.com/grafana/grafana/pkg/services/user" res "github.com/grafana/grafana/pkg/storage/unified/resource" "github.com/grafana/grafana/pkg/storage/unified/resourcepb" - "github.com/grafana/grafana/pkg/storage/unified/search" + "github.com/grafana/grafana/pkg/storage/unified/search/builders" ) const ( @@ -129,9 +129,9 @@ func getColumns(fields []string) []*resourcepb.ResourceTableColumnDefinition { for _, field := range fields { switch field { case "email": - columns = append(columns, search.TableColumnDefinitions[search.USER_EMAIL]) + columns = append(columns, builders.TableColumnDefinitions[builders.USER_EMAIL]) case "login": - columns = append(columns, search.TableColumnDefinitions[search.USER_LOGIN]) + columns = append(columns, builders.TableColumnDefinitions[builders.USER_LOGIN]) } } return columns diff --git a/pkg/server/wire_gen.go b/pkg/server/wire_gen.go index 4dc7523cbb6..9d4dcab2f7e 100644 --- a/pkg/server/wire_gen.go +++ b/pkg/server/wire_gen.go @@ -265,6 +265,7 @@ import ( migrations2 "github.com/grafana/grafana/pkg/storage/unified/migrations" "github.com/grafana/grafana/pkg/storage/unified/resource" "github.com/grafana/grafana/pkg/storage/unified/search" + "github.com/grafana/grafana/pkg/storage/unified/search/builders" "github.com/grafana/grafana/pkg/storage/unified/sql" "github.com/grafana/grafana/pkg/tsdb/azuremonitor" "github.com/grafana/grafana/pkg/tsdb/cloud-monitoring" @@ -455,7 +456,7 @@ func Initialize(ctx context.Context, cfg *setting.Cfg, opts Options, apiOpts api if err != nil { return nil, err } - ossDashboardStats := search.ProvideDashboardStats() + ossDashboardStats := builders.ProvideDashboardStats() documentBuilderSupplier := search.ProvideDocumentBuilders(sqlStore, ossDashboardStats) databaseDatabase := database4.ProvideDatabase(sqlStore, tracer) clockClock := clock.ProvideClock() @@ -1102,7 +1103,7 @@ func InitializeForTest(ctx context.Context, t sqlutil.ITestDB, testingT interfac if err != nil { return nil, err } - ossDashboardStats := search.ProvideDashboardStats() + ossDashboardStats := builders.ProvideDashboardStats() documentBuilderSupplier := search.ProvideDocumentBuilders(sqlStore, ossDashboardStats) databaseDatabase := database4.ProvideDatabase(sqlStore, tracer) clockClock := clock.ProvideClock() @@ -1757,7 +1758,7 @@ func InitializeDocumentBuilders(cfg *setting.Cfg) (resource.DocumentBuilderSuppl if err != nil { return nil, err } - ossDashboardStats := search.ProvideDashboardStats() + ossDashboardStats := builders.ProvideDashboardStats() documentBuilderSupplier := search.ProvideDocumentBuilders(sqlStore, ossDashboardStats) return documentBuilderSupplier, nil } diff --git a/pkg/server/wireexts_oss.go b/pkg/server/wireexts_oss.go index 9f069f807fc..4d70c3f2f4c 100644 --- a/pkg/server/wireexts_oss.go +++ b/pkg/server/wireexts_oss.go @@ -66,6 +66,7 @@ import ( "github.com/grafana/grafana/pkg/storage/unified" "github.com/grafana/grafana/pkg/storage/unified/resource" search2 "github.com/grafana/grafana/pkg/storage/unified/search" + "github.com/grafana/grafana/pkg/storage/unified/search/builders" "github.com/grafana/grafana/pkg/storage/unified/sql" ) @@ -138,8 +139,8 @@ var wireExtsBasicSet = wire.NewSet( wire.Bind(new(auth.IDSigner), new(*idimpl.LocalSigner)), manager.ProvideInstaller, wire.Bind(new(plugins.Installer), new(*manager.PluginInstaller)), - search2.ProvideDashboardStats, - wire.Bind(new(search2.DashboardStats), new(*search2.OssDashboardStats)), + builders.ProvideDashboardStats, + wire.Bind(new(builders.DashboardStats), new(*builders.OssDashboardStats)), search2.ProvideDocumentBuilders, sandbox.ProvideService, wire.Bind(new(sandbox.Sandbox), new(*sandbox.Service)), diff --git a/pkg/services/dashboards/service/dashboard_service.go b/pkg/services/dashboards/service/dashboard_service.go index ebf3f24beb6..b63b4a40f96 100644 --- a/pkg/services/dashboards/service/dashboard_service.go +++ b/pkg/services/dashboards/service/dashboard_service.go @@ -57,7 +57,7 @@ import ( "github.com/grafana/grafana/pkg/storage/legacysql/dualwrite" "github.com/grafana/grafana/pkg/storage/unified/resource" "github.com/grafana/grafana/pkg/storage/unified/resourcepb" - "github.com/grafana/grafana/pkg/storage/unified/search" + "github.com/grafana/grafana/pkg/storage/unified/search/builders" "github.com/grafana/grafana/pkg/util" "github.com/grafana/grafana/pkg/util/retryer" ) @@ -479,7 +479,7 @@ func (dr *DashboardServiceImpl) GetDashboardsByLibraryPanelUID(ctx context.Conte Options: &resourcepb.ListOptions{ Fields: []*resourcepb.Requirement{ { - Key: search.DASHBOARD_LIBRARY_PANEL_REFERENCE, + Key: builders.DASHBOARD_LIBRARY_PANEL_REFERENCE, Operator: string(selection.Equals), Values: []string{libraryPanelUID}, }, diff --git a/pkg/services/dashboards/service/dashboard_service_test.go b/pkg/services/dashboards/service/dashboard_service_test.go index 7aa0e07762c..5725cdf193b 100644 --- a/pkg/services/dashboards/service/dashboard_service_test.go +++ b/pkg/services/dashboards/service/dashboard_service_test.go @@ -46,7 +46,7 @@ import ( "github.com/grafana/grafana/pkg/storage/legacysql/dualwrite" "github.com/grafana/grafana/pkg/storage/unified/resource" "github.com/grafana/grafana/pkg/storage/unified/resourcepb" - "github.com/grafana/grafana/pkg/storage/unified/search" + "github.com/grafana/grafana/pkg/storage/unified/search/builders" "github.com/grafana/grafana/pkg/tests/testsuite" "github.com/grafana/grafana/pkg/util/testutil" ) @@ -2654,7 +2654,7 @@ func TestGetDashboardsByLibraryPanelUID(t *testing.T) { k8sCliMock.On("Search", mock.Anything, mock.Anything, mock.MatchedBy(func(req *resourcepb.ResourceSearchRequest) bool { return len(req.Options.Fields) == 1 && - req.Options.Fields[0].Key == search.DASHBOARD_LIBRARY_PANEL_REFERENCE && + req.Options.Fields[0].Key == builders.DASHBOARD_LIBRARY_PANEL_REFERENCE && req.Options.Fields[0].Values[0] == "test-library-panel" })).Return(searchResponse, nil).Once() diff --git a/pkg/services/dashboards/service/search/search_test.go b/pkg/services/dashboards/service/search/search_test.go index 11279799658..0683cbcb55b 100644 --- a/pkg/services/dashboards/service/search/search_test.go +++ b/pkg/services/dashboards/service/search/search_test.go @@ -7,7 +7,7 @@ import ( "github.com/grafana/grafana/pkg/storage/unified/resource" "github.com/grafana/grafana/pkg/storage/unified/resourcepb" - "github.com/grafana/grafana/pkg/storage/unified/search" + "github.com/grafana/grafana/pkg/storage/unified/search/builders" ) // regression test - parsing int32 values from search results was causing a panic @@ -25,11 +25,11 @@ func TestParseResults(t *testing.T) { Type: resourcepb.ResourceTableColumnDefinition_STRING, }, { - Name: search.DASHBOARD_ERRORS_LAST_1_DAYS, + Name: builders.DASHBOARD_ERRORS_LAST_1_DAYS, Type: resourcepb.ResourceTableColumnDefinition_INT64, }, { - Name: search.DASHBOARD_LINK_COUNT, + Name: builders.DASHBOARD_LINK_COUNT, Type: resourcepb.ResourceTableColumnDefinition_INT32, }, { @@ -75,11 +75,11 @@ func TestParseResults(t *testing.T) { Type: resourcepb.ResourceTableColumnDefinition_STRING, }, { - Name: search.DASHBOARD_ERRORS_LAST_1_DAYS, + Name: builders.DASHBOARD_ERRORS_LAST_1_DAYS, Type: resourcepb.ResourceTableColumnDefinition_INT64, }, { - Name: search.DASHBOARD_LINK_COUNT, + Name: builders.DASHBOARD_LINK_COUNT, Type: resourcepb.ResourceTableColumnDefinition_INT32, }, { diff --git a/pkg/storage/unified/search/bleve.go b/pkg/storage/unified/search/bleve.go index 36c68183203..a8c1efb431c 100644 --- a/pkg/storage/unified/search/bleve.go +++ b/pkg/storage/unified/search/bleve.go @@ -32,6 +32,7 @@ import ( "github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess" "github.com/grafana/grafana/pkg/storage/unified/resourcepb" + "github.com/grafana/grafana/pkg/storage/unified/search/builders" authlib "github.com/grafana/authlib/types" @@ -1178,10 +1179,11 @@ func (b *bleveIndex) toBleveSearchRequest(ctx context.Context, req *resourcepb.R facets[f.Field] = bleve.NewFacetRequest(f.Field, int(f.Limit)) } - // Convert resource-specific fields to bleve fields (just considers dashboard fields for now) + // Convert resource-specific fields to bleve fields. + // TODO: use b.fields.Field(f) instead of builders.DashboardFields() to avoid dashboard-specific code in search server. fields := make([]string, 0, len(req.Fields)) for _, f := range req.Fields { - if slices.Contains(DashboardFields(), f) { + if slices.Contains(builders.DashboardFields(), f) { f = resource.SEARCH_FIELD_PREFIX + f } fields = append(fields, f) @@ -1534,7 +1536,8 @@ func getSortFields(req *resourcepb.ResourceSearchRequest) []string { input = field } - if slices.Contains(DashboardFields(), input) { + // TODO: pass fields parameter and use fields.Field(input) instead of builders.DashboardFields() to avoid dashboard-specific code. + if slices.Contains(builders.DashboardFields(), input) { input = resource.SEARCH_FIELD_PREFIX + input } diff --git a/pkg/storage/unified/search/bleve_search_test.go b/pkg/storage/unified/search/bleve_search_test.go index 600dd0cfe04..7374374fd25 100644 --- a/pkg/storage/unified/search/bleve_search_test.go +++ b/pkg/storage/unified/search/bleve_search_test.go @@ -16,6 +16,7 @@ import ( "github.com/grafana/grafana/pkg/storage/unified/resource" "github.com/grafana/grafana/pkg/storage/unified/resourcepb" "github.com/grafana/grafana/pkg/storage/unified/search" + "github.com/grafana/grafana/pkg/storage/unified/search/builders" ) const threshold = 9999 @@ -265,8 +266,8 @@ func newTestDashboardsIndex(t testing.TB, threshold int64, size int64, writer re ctx := identity.WithRequester(context.Background(), &user.SignedInUser{Namespace: "ns"}) - info, err := search.DashboardBuilder(func(ctx context.Context, namespace string, blob resource.BlobSupport) (resource.DocumentBuilder, error) { - return &search.DashboardDocumentBuilder{ + info, err := builders.DashboardBuilder(func(ctx context.Context, namespace string, blob resource.BlobSupport) (resource.DocumentBuilder, error) { + return &builders.DashboardDocumentBuilder{ Namespace: namespace, Blob: blob, Stats: make(map[string]map[string]int64), // empty stats diff --git a/pkg/storage/unified/search/bleve_test.go b/pkg/storage/unified/search/bleve_test.go index 4c66fc4c1b5..2d2e7142eaf 100644 --- a/pkg/storage/unified/search/bleve_test.go +++ b/pkg/storage/unified/search/bleve_test.go @@ -32,6 +32,7 @@ import ( "github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/storage/unified/resource" "github.com/grafana/grafana/pkg/storage/unified/resourcepb" + "github.com/grafana/grafana/pkg/storage/unified/search/builders" ) // This verifies that we close all indexes properly and shutdown all background goroutines from our tests. @@ -76,8 +77,8 @@ func testBleveBackend(t *testing.T, backend *bleveBackend) { t.Run("build dashboards", func(t *testing.T) { key := dashboardskey - info, err := DashboardBuilder(func(ctx context.Context, namespace string, blob resource.BlobSupport) (resource.DocumentBuilder, error) { - return &DashboardDocumentBuilder{ + info, err := builders.DashboardBuilder(func(ctx context.Context, namespace string, blob resource.BlobSupport) (resource.DocumentBuilder, error) { + return &builders.DashboardDocumentBuilder{ Namespace: namespace, Blob: blob, Stats: make(map[string]map[string]int64), // empty stats @@ -107,9 +108,9 @@ func testBleveBackend(t *testing.T, backend *bleveBackend) { Title: "aaa (dash)", Folder: "xxx", Fields: map[string]any{ - DASHBOARD_PANEL_TYPES: []string{"timeseries", "table"}, - DASHBOARD_ERRORS_TODAY: 25, - DASHBOARD_VIEWS_LAST_1_DAYS: 50, + builders.DASHBOARD_PANEL_TYPES: []string{"timeseries", "table"}, + builders.DASHBOARD_ERRORS_TODAY: 25, + builders.DASHBOARD_VIEWS_LAST_1_DAYS: 50, }, Labels: map[string]string{ utils.LabelKeyDeprecatedInternalID: "10", // nolint:staticcheck @@ -140,9 +141,9 @@ func testBleveBackend(t *testing.T, backend *bleveBackend) { Title: "bbb (dash)", Folder: "xxx", Fields: map[string]any{ - DASHBOARD_PANEL_TYPES: []string{"timeseries"}, - DASHBOARD_ERRORS_TODAY: 40, - DASHBOARD_VIEWS_LAST_1_DAYS: 100, + builders.DASHBOARD_PANEL_TYPES: []string{"timeseries"}, + builders.DASHBOARD_ERRORS_TODAY: 40, + builders.DASHBOARD_VIEWS_LAST_1_DAYS: 100, }, Tags: []string{"aa"}, Labels: map[string]string{ @@ -271,15 +272,15 @@ func testBleveBackend(t *testing.T, backend *bleveBackend) { Key: key, }, Limit: 100000, - Fields: []string{DASHBOARD_ERRORS_TODAY, DASHBOARD_VIEWS_LAST_1_DAYS, "fieldThatDoesntExist"}, + Fields: []string{builders.DASHBOARD_ERRORS_TODAY, builders.DASHBOARD_VIEWS_LAST_1_DAYS, "fieldThatDoesntExist"}, SortBy: []*resourcepb.ResourceSearchRequest_Sort{ - {Field: "fields." + DASHBOARD_VIEWS_LAST_1_DAYS, Desc: true}, + {Field: "fields." + builders.DASHBOARD_VIEWS_LAST_1_DAYS, Desc: true}, }, }, nil, nil) require.NoError(t, err) require.Equal(t, 2, len(rsp.Results.Columns)) - require.Equal(t, DASHBOARD_ERRORS_TODAY, rsp.Results.Columns[0].Name) - require.Equal(t, DASHBOARD_VIEWS_LAST_1_DAYS, rsp.Results.Columns[1].Name) + require.Equal(t, builders.DASHBOARD_ERRORS_TODAY, rsp.Results.Columns[0].Name) + require.Equal(t, builders.DASHBOARD_VIEWS_LAST_1_DAYS, rsp.Results.Columns[1].Name) // sorted descending so should start with highest dashboard_views_last_1_days (100) val, err := resource.DecodeCell(rsp.Results.Columns[1], 0, rsp.Results.Rows[0].Cells[1]) require.NoError(t, err) @@ -291,9 +292,9 @@ func testBleveBackend(t *testing.T, backend *bleveBackend) { Key: key, }, Limit: 100000, - Fields: []string{DASHBOARD_ERRORS_TODAY, DASHBOARD_VIEWS_LAST_1_DAYS, "fieldThatDoesntExist"}, + Fields: []string{builders.DASHBOARD_ERRORS_TODAY, builders.DASHBOARD_VIEWS_LAST_1_DAYS, "fieldThatDoesntExist"}, SortBy: []*resourcepb.ResourceSearchRequest_Sort{ - {Field: "fields." + DASHBOARD_VIEWS_LAST_1_DAYS, Desc: true}, + {Field: "fields." + builders.DASHBOARD_VIEWS_LAST_1_DAYS, Desc: true}, }, }, nil, nil) require.NoError(t, err) diff --git a/pkg/storage/unified/search/dashboard.go b/pkg/storage/unified/search/builders/dashboard.go similarity index 96% rename from pkg/storage/unified/search/dashboard.go rename to pkg/storage/unified/search/builders/dashboard.go index 44a822a1b4c..4f8d55111a9 100644 --- a/pkg/storage/unified/search/dashboard.go +++ b/pkg/storage/unified/search/builders/dashboard.go @@ -1,4 +1,4 @@ -package search +package builders import ( "bytes" @@ -15,10 +15,6 @@ import ( "github.com/grafana/grafana/pkg/storage/unified/resourcepb" ) -//------------------------------------------------------------ -// Standard dashboard fields -//------------------------------------------------------------ - const DASHBOARD_SCHEMA_VERSION = "schema_version" const DASHBOARD_LINK_COUNT = "link_count" const DASHBOARD_PANEL_TYPES = "panel_types" @@ -26,10 +22,6 @@ const DASHBOARD_DS_TYPES = "ds_types" const DASHBOARD_TRANSFORMATIONS = "transformation" const DASHBOARD_LIBRARY_PANEL_REFERENCE = "reference.LibraryPanel" -//------------------------------------------------------------ -// The following fields are added in enterprise -//------------------------------------------------------------ - const DASHBOARD_VIEWS_LAST_1_DAYS = "views_last_1_days" const DASHBOARD_VIEWS_LAST_7_DAYS = "views_last_7_days" const DASHBOARD_VIEWS_LAST_30_DAYS = "views_last_30_days" @@ -268,7 +260,6 @@ func (s *DashboardDocumentBuilder) BuildDocument(ctx context.Context, key *resou if err != nil { return nil, err } - // metadata name is the dashboard uid summary.UID = obj.GetName() summary.ID = obj.GetDeprecatedInternalID() // nolint:staticcheck @@ -331,7 +322,6 @@ func (s *DashboardDocumentBuilder) BuildDocument(ctx context.Context, key *resou doc.Fields[DASHBOARD_TRANSFORMATIONS] = transformations } - // Add the stats fields for k, v := range s.Stats[summary.UID] { doc.Fields[k] = v } diff --git a/pkg/storage/unified/search/dashboard_stats.go b/pkg/storage/unified/search/builders/dashboard_stats.go similarity index 94% rename from pkg/storage/unified/search/dashboard_stats.go rename to pkg/storage/unified/search/builders/dashboard_stats.go index c82db38110e..56024275649 100644 --- a/pkg/storage/unified/search/dashboard_stats.go +++ b/pkg/storage/unified/search/builders/dashboard_stats.go @@ -1,4 +1,4 @@ -package search +package builders import ( "context" diff --git a/pkg/storage/unified/search/builders/document.go b/pkg/storage/unified/search/builders/document.go new file mode 100644 index 00000000000..24226cdcc9a --- /dev/null +++ b/pkg/storage/unified/search/builders/document.go @@ -0,0 +1,66 @@ +package builders + +import ( + "context" + + claims "github.com/grafana/authlib/types" + "github.com/grafana/grafana/pkg/infra/db" + "github.com/grafana/grafana/pkg/infra/log" + "github.com/grafana/grafana/pkg/services/store/kind/dashboard" + "github.com/grafana/grafana/pkg/storage/unified/resource" +) + +// All returns all document builders from this package. +// These builders have dependencies on Grafana apps (dashboard and user). +func All(sql db.DB, sprinkles DashboardStats) ([]resource.DocumentBuilderInfo, error) { + dashboards, err := DashboardBuilder(func(ctx context.Context, namespace string, blob resource.BlobSupport) (resource.DocumentBuilder, error) { + logger := log.New("dashboard_builder", "namespace", namespace) + dsinfo := []*dashboard.DatasourceQueryResult{{}} + ns, err := claims.ParseNamespace(namespace) + if err != nil && sql != nil { + rows, err := sql.GetSqlxSession().Query(ctx, "SELECT uid,type,name,is_default FROM data_source WHERE org_id=?", ns.OrgID) + if err != nil { + return nil, err + } + + defer func() { + _ = rows.Close() + }() + + for rows.Next() { + info := &dashboard.DatasourceQueryResult{} + err = rows.Scan(&info.UID, &info.Type, &info.Name, &info.IsDefault) + if err != nil { + return nil, err + } + dsinfo = append(dsinfo, info) + } + } + + var stats map[string]map[string]int64 + if sprinkles != nil { + stats, err = sprinkles.GetStats(ctx, namespace) + if err != nil { + logger.Warn("Failed to get sprinkles", "error", err) + } + } + + return &DashboardDocumentBuilder{ + Namespace: namespace, + Blob: blob, + Stats: stats, + DatasourceLookup: dashboard.CreateDatasourceLookup(dsinfo), + }, nil + }) + + if err != nil { + return nil, err + } + + users, err := GetUserBuilder() + if err != nil { + return nil, err + } + + return []resource.DocumentBuilderInfo{dashboards, users}, nil +} diff --git a/pkg/storage/unified/search/document_test.go b/pkg/storage/unified/search/builders/document_test.go similarity index 79% rename from pkg/storage/unified/search/document_test.go rename to pkg/storage/unified/search/builders/document_test.go index 285f3178120..59c3302c105 100644 --- a/pkg/storage/unified/search/document_test.go +++ b/pkg/storage/unified/search/builders/document_test.go @@ -1,4 +1,4 @@ -package search_test +package builders import ( "context" @@ -14,7 +14,6 @@ import ( "github.com/grafana/grafana/pkg/services/store/kind/dashboard" "github.com/grafana/grafana/pkg/storage/unified/resource" "github.com/grafana/grafana/pkg/storage/unified/resourcepb" - "github.com/grafana/grafana/pkg/storage/unified/search" ) func doSnapshotTests(t *testing.T, builder resource.DocumentBuilder, kind string, key *resourcepb.ResourceKey, names []string) { @@ -36,7 +35,6 @@ func doSnapshotTests(t *testing.T, builder resource.DocumentBuilder, kind string outpath := filepath.Join("testdata", "doc", prefix+"-out.json") - // test path // nolint:gosec expect, _ := os.ReadFile(outpath) if !assert.JSONEq(t, string(expect), string(out)) { @@ -47,6 +45,19 @@ func doSnapshotTests(t *testing.T, builder resource.DocumentBuilder, kind string } } +func TestUserDocumentBuilder(t *testing.T) { + info, err := GetUserBuilder() + require.NoError(t, err) + doSnapshotTests(t, info.Builder, "user", &resourcepb.ResourceKey{ + Namespace: "default", + Group: "iam.grafana.app", + Resource: "users", + }, []string{ + "user-with-login-and-email", + "user-with-login-only", + }) +} + func TestDashboardDocumentBuilder(t *testing.T) { key := &resourcepb.ResourceKey{ Namespace: "default", @@ -54,18 +65,18 @@ func TestDashboardDocumentBuilder(t *testing.T) { Resource: "dashboards", } - info, err := search.DashboardBuilder(func(ctx context.Context, namespace string, blob resource.BlobSupport) (resource.DocumentBuilder, error) { - return &search.DashboardDocumentBuilder{ + info, err := DashboardBuilder(func(ctx context.Context, namespace string, blob resource.BlobSupport) (resource.DocumentBuilder, error) { + return &DashboardDocumentBuilder{ Namespace: namespace, Blob: blob, Stats: map[string]map[string]int64{ "aaa": { - search.DASHBOARD_ERRORS_LAST_1_DAYS: 1, - search.DASHBOARD_ERRORS_LAST_7_DAYS: 1, + DASHBOARD_ERRORS_LAST_1_DAYS: 1, + DASHBOARD_ERRORS_LAST_7_DAYS: 1, }, }, DatasourceLookup: dashboard.CreateDatasourceLookup([]*dashboard.DatasourceQueryResult{{ - Name: "TheDisplayName", // used to be the unique ID! + Name: "TheDisplayName", Type: "my-custom-plugin", UID: "DSUID", }}), @@ -76,12 +87,10 @@ func TestDashboardDocumentBuilder(t *testing.T) { builder, err := info.Namespaced(context.Background(), key.Namespace, nil) require.NoError(t, err) - // Dashboards (custom) doSnapshotTests(t, builder, "dashboard", key, []string{ "aaa", }) - // Standard builder = resource.StandardDocumentBuilder() doSnapshotTests(t, builder, "folder", &resourcepb.ResourceKey{ Namespace: "default", diff --git a/pkg/storage/unified/search/testdata/doc/dashboard-aaa-out.json b/pkg/storage/unified/search/builders/testdata/doc/dashboard-aaa-out.json similarity index 100% rename from pkg/storage/unified/search/testdata/doc/dashboard-aaa-out.json rename to pkg/storage/unified/search/builders/testdata/doc/dashboard-aaa-out.json diff --git a/pkg/storage/unified/search/testdata/doc/dashboard-aaa.json b/pkg/storage/unified/search/builders/testdata/doc/dashboard-aaa.json similarity index 100% rename from pkg/storage/unified/search/testdata/doc/dashboard-aaa.json rename to pkg/storage/unified/search/builders/testdata/doc/dashboard-aaa.json diff --git a/pkg/storage/unified/search/testdata/doc/folder-aaa-out.json b/pkg/storage/unified/search/builders/testdata/doc/folder-aaa-out.json similarity index 100% rename from pkg/storage/unified/search/testdata/doc/folder-aaa-out.json rename to pkg/storage/unified/search/builders/testdata/doc/folder-aaa-out.json diff --git a/pkg/storage/unified/search/testdata/doc/folder-aaa.json b/pkg/storage/unified/search/builders/testdata/doc/folder-aaa.json similarity index 100% rename from pkg/storage/unified/search/testdata/doc/folder-aaa.json rename to pkg/storage/unified/search/builders/testdata/doc/folder-aaa.json diff --git a/pkg/storage/unified/search/testdata/doc/folder-bbb-out.json b/pkg/storage/unified/search/builders/testdata/doc/folder-bbb-out.json similarity index 100% rename from pkg/storage/unified/search/testdata/doc/folder-bbb-out.json rename to pkg/storage/unified/search/builders/testdata/doc/folder-bbb-out.json diff --git a/pkg/storage/unified/search/testdata/doc/folder-bbb.json b/pkg/storage/unified/search/builders/testdata/doc/folder-bbb.json similarity index 100% rename from pkg/storage/unified/search/testdata/doc/folder-bbb.json rename to pkg/storage/unified/search/builders/testdata/doc/folder-bbb.json diff --git a/pkg/storage/unified/search/testdata/doc/playlist-aaa-out.json b/pkg/storage/unified/search/builders/testdata/doc/playlist-aaa-out.json similarity index 100% rename from pkg/storage/unified/search/testdata/doc/playlist-aaa-out.json rename to pkg/storage/unified/search/builders/testdata/doc/playlist-aaa-out.json diff --git a/pkg/storage/unified/search/testdata/doc/playlist-aaa.json b/pkg/storage/unified/search/builders/testdata/doc/playlist-aaa.json similarity index 100% rename from pkg/storage/unified/search/testdata/doc/playlist-aaa.json rename to pkg/storage/unified/search/builders/testdata/doc/playlist-aaa.json diff --git a/pkg/storage/unified/search/testdata/doc/report-aaa-out.json b/pkg/storage/unified/search/builders/testdata/doc/report-aaa-out.json similarity index 100% rename from pkg/storage/unified/search/testdata/doc/report-aaa-out.json rename to pkg/storage/unified/search/builders/testdata/doc/report-aaa-out.json diff --git a/pkg/storage/unified/search/testdata/doc/report-aaa.json b/pkg/storage/unified/search/builders/testdata/doc/report-aaa.json similarity index 100% rename from pkg/storage/unified/search/testdata/doc/report-aaa.json rename to pkg/storage/unified/search/builders/testdata/doc/report-aaa.json diff --git a/pkg/storage/unified/search/testdata/doc/user-example-out.json b/pkg/storage/unified/search/builders/testdata/doc/user-example-out.json similarity index 100% rename from pkg/storage/unified/search/testdata/doc/user-example-out.json rename to pkg/storage/unified/search/builders/testdata/doc/user-example-out.json diff --git a/pkg/storage/unified/search/testdata/doc/user-example.json b/pkg/storage/unified/search/builders/testdata/doc/user-example.json similarity index 100% rename from pkg/storage/unified/search/testdata/doc/user-example.json rename to pkg/storage/unified/search/builders/testdata/doc/user-example.json diff --git a/pkg/storage/unified/search/testdata/doc/user-user-with-login-and-email-out.json b/pkg/storage/unified/search/builders/testdata/doc/user-user-with-login-and-email-out.json similarity index 100% rename from pkg/storage/unified/search/testdata/doc/user-user-with-login-and-email-out.json rename to pkg/storage/unified/search/builders/testdata/doc/user-user-with-login-and-email-out.json diff --git a/pkg/storage/unified/search/testdata/doc/user-user-with-login-and-email.json b/pkg/storage/unified/search/builders/testdata/doc/user-user-with-login-and-email.json similarity index 100% rename from pkg/storage/unified/search/testdata/doc/user-user-with-login-and-email.json rename to pkg/storage/unified/search/builders/testdata/doc/user-user-with-login-and-email.json diff --git a/pkg/storage/unified/search/testdata/doc/user-user-with-login-only-out.json b/pkg/storage/unified/search/builders/testdata/doc/user-user-with-login-only-out.json similarity index 100% rename from pkg/storage/unified/search/testdata/doc/user-user-with-login-only-out.json rename to pkg/storage/unified/search/builders/testdata/doc/user-user-with-login-only-out.json diff --git a/pkg/storage/unified/search/testdata/doc/user-user-with-login-only.json b/pkg/storage/unified/search/builders/testdata/doc/user-user-with-login-only.json similarity index 100% rename from pkg/storage/unified/search/testdata/doc/user-user-with-login-only.json rename to pkg/storage/unified/search/builders/testdata/doc/user-user-with-login-only.json diff --git a/pkg/storage/unified/search/user.go b/pkg/storage/unified/search/builders/user.go similarity index 96% rename from pkg/storage/unified/search/user.go rename to pkg/storage/unified/search/builders/user.go index 6a09dade5f7..fdf1fce25e1 100644 --- a/pkg/storage/unified/search/user.go +++ b/pkg/storage/unified/search/builders/user.go @@ -1,4 +1,4 @@ -package search +package builders import ( "bytes" @@ -54,7 +54,6 @@ var _ resource.DocumentBuilder = new(userDocumentBuilder) type userDocumentBuilder struct{} -// BuildDocument implements resource.DocumentBuilder. func (u *userDocumentBuilder) BuildDocument(ctx context.Context, key *resourcepb.ResourceKey, rv int64, value []byte) (*resource.IndexableDocument, error) { user := &iamv0.User{} err := json.NewDecoder(bytes.NewReader(value)).Decode(user) diff --git a/pkg/storage/unified/search/document.go b/pkg/storage/unified/search/document.go index eb0059c010d..fff4c31ead9 100644 --- a/pkg/storage/unified/search/document.go +++ b/pkg/storage/unified/search/document.go @@ -1,87 +1,32 @@ package search import ( - "context" - - claims "github.com/grafana/authlib/types" "github.com/grafana/grafana/pkg/infra/db" - "github.com/grafana/grafana/pkg/infra/log" - "github.com/grafana/grafana/pkg/services/store/kind/dashboard" "github.com/grafana/grafana/pkg/storage/unified/resource" + "github.com/grafana/grafana/pkg/storage/unified/search/builders" ) -// The default list of open source document builders +// StandardDocumentBuilders provides the default list of document builders for open source Grafana. +// It combines the standard document builder with external builders for dashboards and users. type StandardDocumentBuilders struct { sql db.DB - sprinkles DashboardStats + sprinkles builders.DashboardStats } -// Hooked up so wire can fill in different sprinkles -func ProvideDocumentBuilders(sql db.DB, sprinkles DashboardStats) resource.DocumentBuilderSupplier { +func ProvideDocumentBuilders(sql db.DB, sprinkles builders.DashboardStats) resource.DocumentBuilderSupplier { return &StandardDocumentBuilders{sql, sprinkles} } func (s *StandardDocumentBuilders) GetDocumentBuilders() ([]resource.DocumentBuilderInfo, error) { - dashboards, err := DashboardBuilder(func(ctx context.Context, namespace string, blob resource.BlobSupport) (resource.DocumentBuilder, error) { - logger := log.New("dashboard_builder", "namespace", namespace) - dsinfo := []*dashboard.DatasourceQueryResult{{}} - ns, err := claims.ParseNamespace(namespace) - if err != nil && s.sql != nil { - rows, err := s.sql.GetSqlxSession().Query(ctx, "SELECT uid,type,name,is_default FROM data_source WHERE org_id=?", ns.OrgID) - if err != nil { - return nil, err - } - - defer func() { - _ = rows.Close() - }() - - for rows.Next() { - info := &dashboard.DatasourceQueryResult{} - err = rows.Scan(&info.UID, &info.Type, &info.Name, &info.IsDefault) - if err != nil { - return nil, err - } - dsinfo = append(dsinfo, info) - } - } - - // Fetch dashboard sprinkles for the namespace - // This could take a while if namespace has a lot of dashboards - var stats map[string]map[string]int64 - if s.sprinkles != nil { - stats, err = s.sprinkles.GetStats(ctx, namespace) - if err != nil { - // only log a warning. Don't need to fail the indexer if we can't get sprinkles - logger.Warn("Failed to get sprinkles", "error", err) - } - } - - return &DashboardDocumentBuilder{ - Namespace: namespace, - Blob: blob, - Stats: stats, - DatasourceLookup: dashboard.CreateDatasourceLookup(dsinfo), - }, nil - }) - + all, err := builders.All(s.sql, s.sprinkles) if err != nil { return nil, err } - users, err := GetUserBuilder() - if err != nil { - return nil, err - } - - return []resource.DocumentBuilderInfo{ - // The default builder + result := []resource.DocumentBuilderInfo{ { Builder: resource.StandardDocumentBuilder(), }, - // Dashboard builder - dashboards, - // User builder - users, - }, err + } + return append(result, all...), nil } diff --git a/pkg/storage/unified/search/user_test.go b/pkg/storage/unified/search/user_test.go deleted file mode 100644 index 67b6777f895..00000000000 --- a/pkg/storage/unified/search/user_test.go +++ /dev/null @@ -1,215 +0,0 @@ -package search_test - -import ( - "context" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/selection" - - iamv0 "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1" - "github.com/grafana/grafana/pkg/apimachinery/identity" - "github.com/grafana/grafana/pkg/infra/tracing" - "github.com/grafana/grafana/pkg/services/user" - "github.com/grafana/grafana/pkg/storage/unified/resource" - "github.com/grafana/grafana/pkg/storage/unified/resourcepb" - "github.com/grafana/grafana/pkg/storage/unified/search" -) - -func TestUserDocumentBuilder(t *testing.T) { - info, err := search.GetUserBuilder() - require.NoError(t, err) - doSnapshotTests(t, info.Builder, "user", &resourcepb.ResourceKey{ - Namespace: "default", - Group: "iam.grafana.app", - Resource: "users", - }, []string{ - "user-with-login-and-email", - "user-with-login-only", - }) -} - -func TestUserSearch(t *testing.T) { - key := resource.NamespacedResource{ - Namespace: "default", - Group: iamv0.UserResourceInfo.GroupResource().Group, - Resource: iamv0.UserResourceInfo.GroupResource().Resource, - } - - index := newTestUsersIndex(t, 100, 2, func(index resource.ResourceIndex) (int64, error) { - return 0, nil - }) - users := []iamv0.User{ - { - ObjectMeta: metav1.ObjectMeta{ - Name: "user1", - Namespace: "default", - }, - Spec: iamv0.UserSpec{ - Login: "user.one", - Email: "user.one@test.com", - Role: "Viewer", - }, - }, - { - ObjectMeta: metav1.ObjectMeta{ - Name: "user2", - Namespace: "default", - }, - Spec: iamv0.UserSpec{ - Login: "user.two", - Email: "user.two@test.com", - Role: "Viewer", - }, - }, - } - indexUserDocuments(t, index, key, users) - - // Sanity check - title search - checkUserSearchQuery(t, index, newTestsUserQueryWithTitle(key, "user2"), []string{"user2"}) - - t.Run("can search users by login", func(t *testing.T) { - // Search by login - checkUserSearchQuery(t, index, newTestUserQueryWithReqs(key, []*resourcepb.Requirement{ - { - Key: "fields.login", - Operator: string(selection.Equals), - Values: []string{"user.one"}, - }, - }), []string{"user1"}) - checkUserSearchQuery(t, index, newTestUserQueryWithReqs(key, []*resourcepb.Requirement{ - { - Key: "fields.login", - Operator: string(selection.Equals), - Values: []string{"user.two"}, - }, - }), []string{"user2"}) - }) - - t.Run("can search users by wildcard login", func(t *testing.T) { - checkUserSearchQuery(t, index, newTestUserQueryWithReqs(key, []*resourcepb.Requirement{ - { - Key: "fields.login", - Operator: string(selection.Equals), - Values: []string{"user.*"}, - }, - }), []string{"user1", "user2"}) - }) - - t.Run("can search users by email", func(t *testing.T) { - // Search by email - checkUserSearchQuery(t, index, newTestUserQueryWithReqs(key, []*resourcepb.Requirement{ - { - Key: "fields.email", - Operator: string(selection.Equals), - Values: []string{"user.one@test.com"}, - }, - }), []string{"user1"}) - - checkUserSearchQuery(t, index, newTestUserQueryWithReqs(key, []*resourcepb.Requirement{ - { - Key: "fields.email", - Operator: string(selection.Equals), - Values: []string{"user.two@test.com"}, - }, - }), []string{"user2"}) - }) -} - -func newTestUsersIndex(t testing.TB, threshold int64, size int64, writer resource.BuildFn) resource.ResourceIndex { - t.Helper() - gr := iamv0.UserResourceInfo.GroupResource() - key := &resourcepb.ResourceKey{ - Namespace: "default", - Group: gr.Group, - Resource: gr.Resource, - } - backend, err := search.NewBleveBackend(search.BleveOptions{ - Root: t.TempDir(), - FileThreshold: threshold, // use in-memory for tests - }, tracing.NewNoopTracerService(), nil) - require.NoError(t, err) - - t.Cleanup(backend.Stop) - - ctx := identity.WithRequester(context.Background(), &user.SignedInUser{Namespace: "ns"}) - - info, err := search.GetUserBuilder() - require.NoError(t, err) - - index, err := backend.BuildIndex(ctx, resource.NamespacedResource{ - Namespace: key.Namespace, - Group: key.Group, - Resource: key.Resource, - }, size, info.Fields, "test", writer, nil, false) - require.NoError(t, err) - - return index -} - -func indexUserDocuments(t *testing.T, index resource.ResourceIndex, key resource.NamespacedResource, users []iamv0.User) { - t.Helper() - items := make([]*resource.BulkIndexItem, 0, len(users)) - for _, user := range users { - items = append(items, &resource.BulkIndexItem{ - Action: resource.ActionIndex, - Doc: &resource.IndexableDocument{ - RV: 1, - Name: user.Name, - Key: &resourcepb.ResourceKey{ - Name: user.Name, - Namespace: key.Namespace, - Group: key.Group, - Resource: key.Resource, - }, - Title: user.Name, - Fields: map[string]any{search.USER_LOGIN: user.Spec.Login, search.USER_EMAIL: user.Spec.Email}, - }, - }) - } - req := &resource.BulkIndexRequest{Items: items} - require.NoError(t, index.BulkIndex(req)) -} - -func checkUserSearchQuery(t *testing.T, index resource.ResourceIndex, query *resourcepb.ResourceSearchRequest, orderedExpectedNames []string) { - t.Helper() - res, err := index.Search(context.Background(), nil, query, nil, nil) - require.NoError(t, err) - require.Equal(t, int64(len(orderedExpectedNames)), res.TotalHits) - names := make([]string, len(res.Results.Rows)) - for ix, row := range res.Results.Rows { - names[ix] = row.Key.Name - } - assert.ElementsMatch(t, orderedExpectedNames, names) -} - -func newTestUserQueryWithReqs(key resource.NamespacedResource, filterReqs []*resourcepb.Requirement) *resourcepb.ResourceSearchRequest { - return &resourcepb.ResourceSearchRequest{ - Options: &resourcepb.ListOptions{ - Key: &resourcepb.ResourceKey{ - Namespace: key.Namespace, - Group: key.Group, - Resource: key.Resource, - }, - Fields: filterReqs, - }, - Limit: 100, - } -} - -func newTestsUserQueryWithTitle(key resource.NamespacedResource, title string) *resourcepb.ResourceSearchRequest { - return &resourcepb.ResourceSearchRequest{ - Options: &resourcepb.ListOptions{ - Key: &resourcepb.ResourceKey{ - Namespace: key.Namespace, - Group: key.Group, - Resource: key.Resource, - }, - }, - Query: title, - Limit: 100, - } -}