refactor(unified-storage): move builders in their own package (#114375)
This commit is contained in:
@@ -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=
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
|
||||
@@ -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
|
||||
|
||||
Generated
+4
-3
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)),
|
||||
|
||||
@@ -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},
|
||||
},
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
{
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
+1
-11
@@ -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
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package search
|
||||
package builders
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -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
|
||||
}
|
||||
+19
-10
@@ -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",
|
||||
@@ -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)
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user