diff --git a/go.mod b/go.mod index b848514cea4..f22d410c51f 100644 --- a/go.mod +++ b/go.mod @@ -52,7 +52,7 @@ require ( github.com/crewjam/saml v0.4.14 // @grafana/identity-access-team github.com/dgraph-io/badger/v4 v4.7.0 // @grafana/grafana-search-and-storage github.com/dlmiddlecote/sqlstats v1.0.2 // @grafana/grafana-backend-group - github.com/docker/go-connections v0.6.0 // indirect; @grafana/grafana-app-platform-squad + github.com/docker/go-connections v0.6.0 // @grafana/grafana-app-platform-squad github.com/dolthub/go-mysql-server v0.19.1-0.20250410182021-5632d67cd46e // @grafana/grafana-datasources-core-services github.com/dolthub/vitess v0.0.0-20250930230441-70c2c6a98e33 // @grafana/grafana-datasources-core-services github.com/dustin/go-humanize v1.0.1 // @grafana/observability-traces-and-profiling diff --git a/pkg/api/api.go b/pkg/api/api.go index da1efa5067f..141883ae21b 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -327,11 +327,6 @@ func (hs *HTTPServer) registerRoutes() { apiRoute.Group("/storage", hs.StorageService.RegisterHTTPRoutes) } - //nolint:staticcheck // not yet migrated to OpenFeature - if hs.Features.IsEnabledGlobally(featuremgmt.FlagPanelTitleSearch) { - apiRoute.Group("/search-v2", hs.SearchV2HTTPService.RegisterHTTPRoutes) - } - // current org apiRoute.Group("/org", func(orgRoute routing.RouteRegister) { userIDScope := ac.Scope("users", "id", ac.Parameter(":userId")) diff --git a/pkg/api/http_server.go b/pkg/api/http_server.go index 0898a5ecb66..b8c1d24f070 100644 --- a/pkg/api/http_server.go +++ b/pkg/api/http_server.go @@ -25,7 +25,6 @@ import ( "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" - "github.com/youmark/pkcs8" "github.com/grafana/grafana/pkg/api/avatar" @@ -95,7 +94,6 @@ import ( "github.com/grafana/grafana/pkg/services/quota" "github.com/grafana/grafana/pkg/services/rendering" "github.com/grafana/grafana/pkg/services/search" - "github.com/grafana/grafana/pkg/services/searchV2" "github.com/grafana/grafana/pkg/services/searchusers" "github.com/grafana/grafana/pkg/services/secrets" secretsKV "github.com/grafana/grafana/pkg/services/secrets/kvstore" @@ -160,7 +158,6 @@ type HTTPServer struct { Live *live.GrafanaLive LivePushGateway *pushhttp.Gateway StorageService store.StorageService - SearchV2HTTPService searchV2.SearchHTTPService ContextHandler *contexthandler.ContextHandler LoggerMiddleware loggermw.Logger SQLStore db.DB @@ -271,7 +268,7 @@ func ProvideHTTPServer(opts ServerOptions, cfg *setting.Cfg, routeRegister routi publicDashboardsApi *publicdashboardsApi.Api, userService user.Service, tempUserService tempUser.Service, loginAttemptService loginAttempt.Service, orgService org.Service, orgDeletionService org.DeletionService, teamService team.Service, accesscontrolService accesscontrol.Service, navTreeService navtree.Service, - annotationRepo annotations.Repository, tagService tag.Service, searchv2HTTPService searchV2.SearchHTTPService, oauthTokenService oauthtoken.OAuthTokenService, + annotationRepo annotations.Repository, tagService tag.Service, oauthTokenService oauthtoken.OAuthTokenService, statsService stats.Service, authnService authn.Service, pluginsCDNService *pluginscdn.Service, promGatherer prometheus.Gatherer, starApi *starApi.API, promRegister prometheus.Registerer, clientConfigProvider grafanaapiserver.DirectRestConfigProvider, anonService anonymous.Service, userVerifier user.Verifier, pluginPreinstall pluginchecker.Preinstall, @@ -313,7 +310,6 @@ func ProvideHTTPServer(opts ServerOptions, cfg *setting.Cfg, routeRegister routi ProvisioningService: provisioningService, AccessControl: accessControl, DataProxy: dataSourceProxy, - SearchV2HTTPService: searchv2HTTPService, SearchService: searchService, Live: live, LivePushGateway: livePushGateway, diff --git a/pkg/extensions/enterprise_imports.go b/pkg/extensions/enterprise_imports.go index 113c2f8e4bb..472652cc103 100644 --- a/pkg/extensions/enterprise_imports.go +++ b/pkg/extensions/enterprise_imports.go @@ -15,6 +15,7 @@ import ( _ "github.com/blugelabs/bluge" _ "github.com/blugelabs/bluge_segment_api" _ "github.com/crewjam/saml" + _ "github.com/docker/go-connections/nat" _ "github.com/go-jose/go-jose/v4" _ "github.com/gobwas/glob" _ "github.com/googleapis/gax-go/v2" @@ -30,6 +31,7 @@ import ( _ "github.com/spf13/cobra" // used by the standalone apiserver cli _ "github.com/spyzhov/ajson" _ "github.com/stretchr/testify/require" + _ "github.com/testcontainers/testcontainers-go" _ "gocloud.dev/secrets/awskms" _ "gocloud.dev/secrets/azurekeyvault" _ "gocloud.dev/secrets/gcpkms" @@ -54,9 +56,7 @@ import ( _ "github.com/grafana/e2e" _ "github.com/grafana/gofpdf" _ "github.com/grafana/gomemcache/memcache" - _ "github.com/grafana/tempo/pkg/traceql" - _ "github.com/grafana/grafana/apps/alerting/alertenrichment/pkg/apis/alertenrichment/v1beta1" _ "github.com/grafana/grafana/apps/scope/pkg/apis/scope/v0alpha1" - _ "github.com/testcontainers/testcontainers-go" + _ "github.com/grafana/tempo/pkg/traceql" ) diff --git a/pkg/registry/backgroundsvcs/background_services.go b/pkg/registry/backgroundsvcs/background_services.go index c56fa60051c..2500d3e78c5 100644 --- a/pkg/registry/backgroundsvcs/background_services.go +++ b/pkg/registry/backgroundsvcs/background_services.go @@ -38,7 +38,6 @@ import ( "github.com/grafana/grafana/pkg/services/provisioning" publicdashboardsmetric "github.com/grafana/grafana/pkg/services/publicdashboards/metric" "github.com/grafana/grafana/pkg/services/rendering" - "github.com/grafana/grafana/pkg/services/searchV2" secretsMigrations "github.com/grafana/grafana/pkg/services/secrets/kvstore/migrations" secretsManager "github.com/grafana/grafana/pkg/services/secrets/manager" "github.com/grafana/grafana/pkg/services/serviceaccounts" @@ -58,7 +57,7 @@ func ProvideBackgroundServiceRegistry( provisioning *provisioning.ProvisioningServiceImpl, usageStats *uss.UsageStats, statsCollector *statscollector.Service, grafanaUpdateChecker *updatemanager.GrafanaService, pluginsUpdateChecker *updatemanager.PluginsService, metrics *metrics.InternalMetricsService, - secretsService *secretsManager.SecretsService, remoteCache *remotecache.RemoteCache, StorageService store.StorageService, searchService searchV2.SearchService, entityEventsService store.EntityEventsService, + secretsService *secretsManager.SecretsService, remoteCache *remotecache.RemoteCache, StorageService store.StorageService, entityEventsService store.EntityEventsService, saService *samanager.ServiceAccountsService, grpcServerProvider grpcserver.Provider, secretMigrationProvider secretsMigrations.SecretMigrationProvider, loginAttemptService *loginattemptimpl.Service, bundleService *supportbundlesimpl.Service, publicDashboardsMetric *publicdashboardsmetric.Service, @@ -101,7 +100,6 @@ func ProvideBackgroundServiceRegistry( remoteCache, secretsService, StorageService, - searchService, entityEventsService, grpcServerProvider, saService, diff --git a/pkg/server/wire.go b/pkg/server/wire.go index 9864bed4e12..f63144c052e 100644 --- a/pkg/server/wire.go +++ b/pkg/server/wire.go @@ -140,7 +140,6 @@ import ( "github.com/grafana/grafana/pkg/services/rendering" "github.com/grafana/grafana/pkg/services/search" "github.com/grafana/grafana/pkg/services/search/sort" - "github.com/grafana/grafana/pkg/services/searchV2" "github.com/grafana/grafana/pkg/services/secrets" secretsDatabase "github.com/grafana/grafana/pkg/services/secrets/database" secretsStore "github.com/grafana/grafana/pkg/services/secrets/kvstore" @@ -275,8 +274,6 @@ var wireBasicSet = wire.NewSet( datasourceproxy.ProvideService, sort.ProvideService, search.ProvideService, - searchV2.ProvideService, - searchV2.ProvideSearchHTTPService, store.ProvideService, store.ProvideSystemUsersService, live.ProvideService, diff --git a/pkg/server/wire_gen.go b/pkg/server/wire_gen.go index 676b0605e83..87c964de858 100644 --- a/pkg/server/wire_gen.go +++ b/pkg/server/wire_gen.go @@ -68,14 +68,14 @@ import ( "github.com/grafana/grafana/pkg/registry/apis/secret/clock" "github.com/grafana/grafana/pkg/registry/apis/secret/contracts" "github.com/grafana/grafana/pkg/registry/apis/secret/decrypt" - service4 "github.com/grafana/grafana/pkg/registry/apis/secret/encryption/cipher/service" + service5 "github.com/grafana/grafana/pkg/registry/apis/secret/encryption/cipher/service" "github.com/grafana/grafana/pkg/registry/apis/secret/encryption/kmsproviders" - manager2 "github.com/grafana/grafana/pkg/registry/apis/secret/encryption/manager" + manager3 "github.com/grafana/grafana/pkg/registry/apis/secret/encryption/manager" "github.com/grafana/grafana/pkg/registry/apis/secret/garbagecollectionworker" "github.com/grafana/grafana/pkg/registry/apis/secret/inline" "github.com/grafana/grafana/pkg/registry/apis/secret/mutator" "github.com/grafana/grafana/pkg/registry/apis/secret/secretkeeper" - service5 "github.com/grafana/grafana/pkg/registry/apis/secret/service" + service6 "github.com/grafana/grafana/pkg/registry/apis/secret/service" "github.com/grafana/grafana/pkg/registry/apis/secret/validator" "github.com/grafana/grafana/pkg/registry/apis/userstorage" "github.com/grafana/grafana/pkg/registry/apps" @@ -195,7 +195,7 @@ import ( "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginerrs" "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginexternal" "github.com/grafana/grafana/pkg/services/pluginsintegration/plugininstaller" - service6 "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsettings/service" + service3 "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsettings/service" "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsso" "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore" "github.com/grafana/grafana/pkg/services/pluginsintegration/provisionedplugins" @@ -209,14 +209,13 @@ import ( api2 "github.com/grafana/grafana/pkg/services/publicdashboards/api" database3 "github.com/grafana/grafana/pkg/services/publicdashboards/database" "github.com/grafana/grafana/pkg/services/publicdashboards/metric" - service3 "github.com/grafana/grafana/pkg/services/publicdashboards/service" + service4 "github.com/grafana/grafana/pkg/services/publicdashboards/service" "github.com/grafana/grafana/pkg/services/query" "github.com/grafana/grafana/pkg/services/queryhistory" "github.com/grafana/grafana/pkg/services/quota/quotaimpl" "github.com/grafana/grafana/pkg/services/rendering" search2 "github.com/grafana/grafana/pkg/services/search" "github.com/grafana/grafana/pkg/services/search/sort" - "github.com/grafana/grafana/pkg/services/searchV2" "github.com/grafana/grafana/pkg/services/searchusers" "github.com/grafana/grafana/pkg/services/searchusers/filters" "github.com/grafana/grafana/pkg/services/secrets" @@ -227,7 +226,7 @@ import ( migrator2 "github.com/grafana/grafana/pkg/services/secrets/migrator" "github.com/grafana/grafana/pkg/services/serviceaccounts" "github.com/grafana/grafana/pkg/services/serviceaccounts/extsvcaccounts" - manager3 "github.com/grafana/grafana/pkg/services/serviceaccounts/manager" + manager2 "github.com/grafana/grafana/pkg/services/serviceaccounts/manager" "github.com/grafana/grafana/pkg/services/serviceaccounts/proxy" "github.com/grafana/grafana/pkg/services/serviceaccounts/retriever" "github.com/grafana/grafana/pkg/services/shorturls" @@ -407,12 +406,24 @@ func Initialize(ctx context.Context, cfg *setting.Cfg, opts Options, apiOpts api postgresService := postgres.ProvideService() mysqlService := mysql.ProvideService() mssqlService := mssql.ProvideService(cfg) - entityEventsService := store.ProvideEntityEventsService(cfg, sqlStore, featureToggles) configProvider, err := configprovider.ProvideService(cfg) if err != nil { return nil, err } quotaService := quotaimpl.ProvideService(ctx, sqlStore, configProvider) + systemUsers := store.ProvideSystemUsersService() + storageService, err := store.ProvideService(sqlStore, featureToggles, cfg, quotaService, systemUsers) + if err != nil { + return nil, err + } + grafanadsService := grafanads.ProvideService(storageService, featureToggles) + pyroscopeService := pyroscope.ProvideService(httpclientProvider) + parcaService := parca.ProvideService(httpclientProvider) + zipkinService := zipkin.ProvideService(httpclientProvider) + jaegerService := jaeger.ProvideService(httpclientProvider) + corepluginRegistry := coreplugin.ProvideCoreRegistry(tracingService, azuremonitorService, cloudwatchService, cloudmonitoringService, elasticsearchService, graphiteService, influxdbService, lokiService, opentsdbService, prometheusService, tempoService, testdatasourceService, postgresService, mysqlService, mssqlService, grafanadsService, pyroscopeService, parcaService, zipkinService, jaegerService) + providerService := provider2.ProvideService(corepluginRegistry) + processService := process.ProvideService() orgService, err := orgimpl.ProvideService(sqlStore, cfg, quotaService) if err != nil { return nil, err @@ -432,18 +443,45 @@ func Initialize(ctx context.Context, cfg *setting.Cfg, opts Options, apiOpts api if err != nil { return nil, err } - folderStoreImpl := folderimpl.ProvideStore(sqlStore) + apikeyService, err := apikeyimpl.ProvideService(sqlStore, cfg, quotaService) + if err != nil { + return nil, err + } + retrieverService := retriever.ProvideService(sqlStore, apikeyService, kvStore, userService, orgService) + serviceAccountPermissionsService, err := ossaccesscontrol.ProvideServiceAccountPermissions(cfg, featureToggles, routeRegisterImpl, sqlStore, accessControl, ossLicensingService, retrieverService, acimplService, teamService, userService, actionSetService) + if err != nil { + return nil, err + } + serviceAccountsService, err := manager2.ProvideServiceAccountsService(cfg, usageStats, sqlStore, apikeyService, kvStore, userService, orgService, acimplService, serviceAccountPermissionsService, serverLockService) + if err != nil { + return nil, err + } + extSvcAccountsService := extsvcaccounts.ProvideExtSvcAccountsService(acimplService, cfg, inProcBus, sqlStore, featureToggles, registerer, serviceAccountsService, secretsService, tracingService) + registryRegistry := registry2.ProvideExtSvcRegistry(cfg, extSvcAccountsService, serverLockService, featureToggles) + service13 := service3.ProvideService(sqlStore, secretsService) + serviceregistrationService := serviceregistration.ProvideService(cfg, featureToggles, registryRegistry, service13) + noop := provisionedplugins.NewNoop() + initialize := pipeline.ProvideInitializationStage(pluginManagementCfg, inMemory, providerService, processService, serviceregistrationService, acimplService, actionSetService, envVarsProvider, tracingService, noop) + terminate, err := pipeline.ProvideTerminationStage(pluginManagementCfg, inMemory, processService) + if err != nil { + return nil, err + } + errorRegistry := pluginerrs.ProvideErrorTracker() + loaderLoader := loader.ProvideService(pluginManagementCfg, discovery, bootstrap, validate, initialize, terminate, errorRegistry) + pluginstoreService, err := pluginstore.ProvideService(inMemory, sourcesService, loaderLoader, featureToggles) + if err != nil { + return nil, err + } + filestoreService := filestore.ProvideService(inMemory) + fileStoreManager := dashboards.ProvideFileStoreManager(pluginstoreService, filestoreService) tagimplService := tagimpl.ProvideService(sqlStore) dashboardsStore, err := database2.ProvideDashboardStore(sqlStore, cfg, featureToggles, tagimplService) if err != nil { return nil, err } + folderStoreImpl := folderimpl.ProvideStore(sqlStore) publicDashboardStoreImpl := database3.ProvideStore(sqlStore, cfg, featureToggles) - publicDashboardServiceWrapperImpl := service3.ProvideServiceWrapper(publicDashboardStoreImpl) - apikeyService, err := apikeyimpl.ProvideService(sqlStore, cfg, quotaService) - if err != nil { - return nil, err - } + publicDashboardServiceWrapperImpl := service4.ProvideServiceWrapper(publicDashboardStoreImpl) contextHandler := grpccontext.ProvideContextHandler(tracingService) authenticator := interceptors.ProvideAuthenticator(apikeyService, userService, acimplService, contextHandler) grpcserverProvider, err := grpcserver.ProvideService(cfg, featureToggles, authenticator, tracer, registerer) @@ -481,7 +519,7 @@ func Initialize(ctx context.Context, cfg *setting.Cfg, opts Options, apiOpts api if err != nil { return nil, err } - cipher, err := service4.ProvideAESGCMCipherService(tracer, usageStats) + cipher, err := service5.ProvideAESGCMCipherService(tracer, usageStats) if err != nil { return nil, err } @@ -489,7 +527,7 @@ func Initialize(ctx context.Context, cfg *setting.Cfg, opts Options, apiOpts api if err != nil { return nil, err } - encryptionManager, err := manager2.ProvideEncryptionManager(tracer, dataKeyStorage, usageStats, cipher, providerConfig) + encryptionManager, err := manager3.ProvideEncryptionManager(tracer, dataKeyStorage, usageStats, cipher, providerConfig) if err != nil { return nil, err } @@ -510,7 +548,7 @@ func Initialize(ctx context.Context, cfg *setting.Cfg, opts Options, apiOpts api if err != nil { return nil, err } - secureValueService := service5.ProvideSecureValueService(tracer, accessClient, secureValueMetadataStorage, secureValueValidator, secureValueMutator, keeperMetadataStorage, ossKeeperService, registerer) + secureValueService := service6.ProvideSecureValueService(tracer, accessClient, secureValueMetadataStorage, secureValueValidator, secureValueMutator, keeperMetadataStorage, ossKeeperService, registerer) inlineSecureValueSupport, err := inline.ProvideInlineSecureValueService(cfg, tracer, secureValueService, accessClient) if err != nil { return nil, err @@ -545,47 +583,6 @@ func Initialize(ctx context.Context, cfg *setting.Cfg, opts Options, apiOpts api } sortService := sort.ProvideService() folderimplService := folderimpl.ProvideService(folderStoreImpl, accessControl, inProcBus, dashboardsStore, userService, sqlStore, featureToggles, bundleregistryService, publicDashboardServiceWrapperImpl, cfg, registerer, tracer, resourceClient, dualwriteService, sortService, eventualRestConfigProvider) - searchService := searchV2.ProvideService(cfg, sqlStore, entityEventsService, acimplService, tracingService, featureToggles, orgService, userService, folderimplService) - systemUsers := store.ProvideSystemUsersService() - storageService, err := store.ProvideService(sqlStore, featureToggles, cfg, quotaService, systemUsers) - if err != nil { - return nil, err - } - grafanadsService := grafanads.ProvideService(searchService, storageService, featureToggles) - pyroscopeService := pyroscope.ProvideService(httpclientProvider) - parcaService := parca.ProvideService(httpclientProvider) - zipkinService := zipkin.ProvideService(httpclientProvider) - jaegerService := jaeger.ProvideService(httpclientProvider) - corepluginRegistry := coreplugin.ProvideCoreRegistry(tracingService, azuremonitorService, cloudwatchService, cloudmonitoringService, elasticsearchService, graphiteService, influxdbService, lokiService, opentsdbService, prometheusService, tempoService, testdatasourceService, postgresService, mysqlService, mssqlService, grafanadsService, pyroscopeService, parcaService, zipkinService, jaegerService) - providerService := provider2.ProvideService(corepluginRegistry) - processService := process.ProvideService() - retrieverService := retriever.ProvideService(sqlStore, apikeyService, kvStore, userService, orgService) - serviceAccountPermissionsService, err := ossaccesscontrol.ProvideServiceAccountPermissions(cfg, featureToggles, routeRegisterImpl, sqlStore, accessControl, ossLicensingService, retrieverService, acimplService, teamService, userService, actionSetService) - if err != nil { - return nil, err - } - serviceAccountsService, err := manager3.ProvideServiceAccountsService(cfg, usageStats, sqlStore, apikeyService, kvStore, userService, orgService, acimplService, serviceAccountPermissionsService, serverLockService) - if err != nil { - return nil, err - } - extSvcAccountsService := extsvcaccounts.ProvideExtSvcAccountsService(acimplService, cfg, inProcBus, sqlStore, featureToggles, registerer, serviceAccountsService, secretsService, tracingService) - registryRegistry := registry2.ProvideExtSvcRegistry(cfg, extSvcAccountsService, serverLockService, featureToggles) - service13 := service6.ProvideService(sqlStore, secretsService) - serviceregistrationService := serviceregistration.ProvideService(cfg, featureToggles, registryRegistry, service13) - noop := provisionedplugins.NewNoop() - initialize := pipeline.ProvideInitializationStage(pluginManagementCfg, inMemory, providerService, processService, serviceregistrationService, acimplService, actionSetService, envVarsProvider, tracingService, noop) - terminate, err := pipeline.ProvideTerminationStage(pluginManagementCfg, inMemory, processService) - if err != nil { - return nil, err - } - errorRegistry := pluginerrs.ProvideErrorTracker() - loaderLoader := loader.ProvideService(pluginManagementCfg, discovery, bootstrap, validate, initialize, terminate, errorRegistry) - pluginstoreService, err := pluginstore.ProvideService(inMemory, sourcesService, loaderLoader, featureToggles) - if err != nil { - return nil, err - } - filestoreService := filestore.ProvideService(inMemory) - fileStoreManager := dashboards.ProvideFileStoreManager(pluginstoreService, filestoreService) folderPermissionsService, err := ossaccesscontrol.ProvideFolderPermissions(cfg, featureToggles, routeRegisterImpl, sqlStore, accessControl, ossLicensingService, folderimplService, acimplService, teamService, userService, actionSetService, eventualRestConfigProvider) if err != nil { return nil, err @@ -665,13 +662,13 @@ func Initialize(ctx context.Context, cfg *setting.Cfg, opts Options, apiOpts api azurePromMigrationService := promtypemigration.ProvideAzurePromMigrationService(service15, inMemory, repoManager, pluginInstaller, cfg) amazonPromMigrationService := promtypemigration.ProvideAmazonPromMigrationService(service15, inMemory, repoManager, pluginInstaller, cfg) promTypeMigrationProviderImpl := promtypemigration.ProvidePromTypeMigrationProvider(serverLockService, featureToggles, azurePromMigrationService, amazonPromMigrationService) - provisioningServiceImpl, err := provisioning.ProvideService(accessControl, cfg, sqlStore, pluginstoreService, dBstore, serviceService, notificationService, dashboardProvisioningService, service15, correlationsService, dashboardService, folderimplService, service13, searchService, quotaService, secretsService, orgService, receiverPermissionsService, tracingService, dualwriteService, promTypeMigrationProviderImpl, serverLockService) + provisioningServiceImpl, err := provisioning.ProvideService(accessControl, cfg, sqlStore, pluginstoreService, dBstore, serviceService, notificationService, dashboardProvisioningService, service15, correlationsService, dashboardService, folderimplService, service13, quotaService, secretsService, orgService, receiverPermissionsService, tracingService, dualwriteService, promTypeMigrationProviderImpl, serverLockService) if err != nil { return nil, err } dataSourceProxyService := datasourceproxy.ProvideService(cacheServiceImpl, ossDataSourceRequestValidator, pluginstoreService, cfg, httpclientProvider, oauthtokenService, service15, tracingService, secretsService, featureToggles) starService := starimpl.ProvideService(sqlStore) - searchSearchService := search2.ProvideService(cfg, sqlStore, starService, dashboardService, folderimplService, featureToggles, sortService) + searchService := search2.ProvideService(cfg, sqlStore, starService, dashboardService, folderimplService, featureToggles, sortService) plugincontextProvider := plugincontext.ProvideService(cfg, cacheService, pluginstoreService, cacheServiceImpl, service15, service13, requestConfigProvider) dashboardAccessService := service7.ProvideDashboardAccessService(featureToggles, dashboardServiceImpl) grafanaLive, err := live.ProvideService(cfg, routeRegisterImpl, plugincontextProvider, pluginstoreService, middlewareHandler, cacheServiceImpl, usageStats, featureToggles, dashboardAccessService, eventualRestConfigProvider) @@ -727,7 +724,7 @@ func Initialize(ctx context.Context, cfg *setting.Cfg, opts Options, apiOpts api secretsMigrator := migrator2.ProvideSecretsMigrator(serviceService, secretsService, sqlStore, ossImpl, featureToggles) dataSourceSecretMigrationService := migrations3.ProvideDataSourceMigrationService(service15, kvStore, featureToggles) secretMigrationProviderImpl := migrations3.ProvideSecretMigrationProvider(serverLockService, dataSourceSecretMigrationService) - publicDashboardServiceImpl := service3.ProvideService(cfg, featureToggles, publicDashboardStoreImpl, queryServiceImpl, repositoryImpl, accessControl, publicDashboardServiceWrapperImpl, dashboardService, ossLicensingService) + publicDashboardServiceImpl := service4.ProvideService(cfg, featureToggles, publicDashboardStoreImpl, queryServiceImpl, repositoryImpl, accessControl, publicDashboardServiceWrapperImpl, dashboardService, ossLicensingService) middleware := api2.ProvideMiddleware() apiApi := api2.ProvideApi(publicDashboardServiceImpl, routeRegisterImpl, accessControl, featureToggles, middleware, cfg, ossLicensingService) loginattemptimplService := loginattemptimpl.ProvideService(sqlStore, cfg, serverLockService) @@ -737,7 +734,6 @@ func Initialize(ctx context.Context, cfg *setting.Cfg, opts Options, apiOpts api } authnService := authnimpl.ProvideAuthnService(authnimplService) navtreeService := navtreeimpl.ProvideService(cfg, accessControl, pluginstoreService, service13, starService, featureToggles, dashboardService, acimplService, kvStore, apikeyService, ossLicensingService, authnService) - searchHTTPService := searchV2.ProvideSearchHTTPService(searchService) statsService := statsimpl.ProvideService(cfg, sqlStore, dashboardService, folderimplService, orgService, resourceClient, featureToggles) gatherer := metrics.ProvideGatherer() apiAPI := api3.ProvideApi(cfg, featureToggles, starService, eventualRestConfigProvider) @@ -753,7 +749,7 @@ func Initialize(ctx context.Context, cfg *setting.Cfg, opts Options, apiOpts api } idimplService := idimpl.ProvideService(cfg, localSigner, remoteCache, authnService, registerer, tracer) verifier := userimpl.ProvideVerifier(cfg, userService, tempuserService, notificationService, idimplService) - httpServer, err := api.ProvideHTTPServer(apiOpts, cfg, routeRegisterImpl, inProcBus, renderingService, ossLicensingService, hooksService, cacheService, sqlStore, ossDataSourceRequestValidator, pluginstoreService, service14, pluginstoreService, middlewareHandler, pluginerrsStore, pluginInstaller, ossImpl, cacheServiceImpl, userAuthTokenService, cleanUpService, shortURLService, queryHistoryService, correlationsService, remoteCache, provisioningServiceImpl, accessControl, dataSourceProxyService, searchSearchService, grafanaLive, gateway, plugincontextProvider, contexthandlerContextHandler, logger, featureToggles, alertNG, libraryPanelService, libraryElementService, quotaService, socialService, tracingService, serviceService, grafanaService, pluginsService, ossService, service15, queryServiceImpl, filestoreService, serviceAccountsProxy, pluginassetsService, authinfoimplService, storageService, notificationService, dashboardService, dashboardProvisioningService, folderimplService, ossProvider, serviceImpl, service13, avatarCacheServer, prefService, folderPermissionsService, dashboardPermissionsService, dashverService, starService, csrfCSRF, managedpluginsNoop, playlistService, apikeyService, kvStore, secretsMigrator, secretsService, secretMigrationProviderImpl, secretsKVStore, apiApi, userService, tempuserService, loginattemptimplService, orgService, deletionService, teamService, acimplService, navtreeService, repositoryImpl, tagimplService, searchHTTPService, oauthtokenService, statsService, authnService, pluginscdnService, gatherer, apiAPI, registerer, eventualRestConfigProvider, anonDeviceService, verifier, preinstallImpl) + httpServer, err := api.ProvideHTTPServer(apiOpts, cfg, routeRegisterImpl, inProcBus, renderingService, ossLicensingService, hooksService, cacheService, sqlStore, ossDataSourceRequestValidator, pluginstoreService, service14, pluginstoreService, middlewareHandler, pluginerrsStore, pluginInstaller, ossImpl, cacheServiceImpl, userAuthTokenService, cleanUpService, shortURLService, queryHistoryService, correlationsService, remoteCache, provisioningServiceImpl, accessControl, dataSourceProxyService, searchService, grafanaLive, gateway, plugincontextProvider, contexthandlerContextHandler, logger, featureToggles, alertNG, libraryPanelService, libraryElementService, quotaService, socialService, tracingService, serviceService, grafanaService, pluginsService, ossService, service15, queryServiceImpl, filestoreService, serviceAccountsProxy, pluginassetsService, authinfoimplService, storageService, notificationService, dashboardService, dashboardProvisioningService, folderimplService, ossProvider, serviceImpl, service13, avatarCacheServer, prefService, folderPermissionsService, dashboardPermissionsService, dashverService, starService, csrfCSRF, managedpluginsNoop, playlistService, apikeyService, kvStore, secretsMigrator, secretsService, secretMigrationProviderImpl, secretsKVStore, apiApi, userService, tempuserService, loginattemptimplService, orgService, deletionService, teamService, acimplService, navtreeService, repositoryImpl, tagimplService, oauthtokenService, statsService, authnService, pluginscdnService, gatherer, apiAPI, registerer, eventualRestConfigProvider, anonDeviceService, verifier, preinstallImpl) if err != nil { return nil, err } @@ -771,6 +767,7 @@ func Initialize(ctx context.Context, cfg *setting.Cfg, opts Options, apiOpts api if err != nil { return nil, err } + entityEventsService := store.ProvideEntityEventsService(cfg, sqlStore, featureToggles) supportbundlesimplService, err := supportbundlesimpl.ProvideService(accessControl, acimplService, bundleregistryService, cfg, featureToggles, httpServer, kvStore, service13, pluginstoreService, routeRegisterImpl, ossImpl, sqlStore, usageStats, tracingService) if err != nil { return nil, err @@ -944,7 +941,7 @@ func Initialize(ctx context.Context, cfg *setting.Cfg, opts Options, apiOpts api } ossUserProtectionImpl := authinfoimpl.ProvideOSSUserProtectionService() registration := authnimpl.ProvideRegistration(cfg, authnService, orgService, userAuthTokenService, acimplService, permissionRegistry, apikeyService, userService, authService, ossUserProtectionImpl, loginattemptimplService, quotaService, authinfoimplService, renderingService, featureToggles, oauthtokenService, socialService, remoteCache, ldapImpl, ossImpl, tracingService, tempuserService, notificationService) - backgroundServiceRegistry := backgroundsvcs.ProvideBackgroundServiceRegistry(httpServer, alertNG, cleanUpService, grafanaLive, gateway, notificationService, pluginstoreService, renderingService, userAuthTokenService, tracingService, provisioningServiceImpl, usageStats, statscollectorService, grafanaService, pluginsService, internalMetricsService, secretsService, remoteCache, storageService, searchService, entityEventsService, serviceAccountsService, grpcserverProvider, secretMigrationProviderImpl, loginattemptimplService, supportbundlesimplService, metricService, keyRetriever, angulardetectorsproviderDynamic, apiserverService, anonDeviceService, ssosettingsimplService, pluginexternalService, plugininstallerService, zanzanaReconciler, appregistryService, dashboardUpdater, dashboardServiceImpl, worker, fixedRolesLoader, syncer, serviceImpl, serviceAccountsProxy, healthService, reflectionService, apiService, apiregistryService, idimplService, teamAPI, ssosettingsimplService, cloudmigrationService, registration) + backgroundServiceRegistry := backgroundsvcs.ProvideBackgroundServiceRegistry(httpServer, alertNG, cleanUpService, grafanaLive, gateway, notificationService, pluginstoreService, renderingService, userAuthTokenService, tracingService, provisioningServiceImpl, usageStats, statscollectorService, grafanaService, pluginsService, internalMetricsService, secretsService, remoteCache, storageService, entityEventsService, serviceAccountsService, grpcserverProvider, secretMigrationProviderImpl, loginattemptimplService, supportbundlesimplService, metricService, keyRetriever, angulardetectorsproviderDynamic, apiserverService, anonDeviceService, ssosettingsimplService, pluginexternalService, plugininstallerService, zanzanaReconciler, appregistryService, dashboardUpdater, dashboardServiceImpl, worker, fixedRolesLoader, syncer, serviceImpl, serviceAccountsProxy, healthService, reflectionService, apiService, apiregistryService, idimplService, teamAPI, ssosettingsimplService, cloudmigrationService, registration) usageStatsProvidersRegistry := usagestatssvcs.ProvideUsageStatsProvidersRegistry(acimplService, userService) server, err := New(opts, cfg, httpServer, acimplService, provisioningServiceImpl, backgroundServiceRegistry, usageStatsProvidersRegistry, statscollectorService, tracingService, featureToggles, registerer) if err != nil { @@ -1067,12 +1064,24 @@ func InitializeForTest(ctx context.Context, t sqlutil.ITestDB, testingT interfac postgresService := postgres.ProvideService() mysqlService := mysql.ProvideService() mssqlService := mssql.ProvideService(cfg) - entityEventsService := store.ProvideEntityEventsService(cfg, sqlStore, featureToggles) configProvider, err := configprovider.ProvideService(cfg) if err != nil { return nil, err } quotaService := quotaimpl.ProvideService(ctx, sqlStore, configProvider) + systemUsers := store.ProvideSystemUsersService() + storageService, err := store.ProvideService(sqlStore, featureToggles, cfg, quotaService, systemUsers) + if err != nil { + return nil, err + } + grafanadsService := grafanads.ProvideService(storageService, featureToggles) + pyroscopeService := pyroscope.ProvideService(httpclientProvider) + parcaService := parca.ProvideService(httpclientProvider) + zipkinService := zipkin.ProvideService(httpclientProvider) + jaegerService := jaeger.ProvideService(httpclientProvider) + corepluginRegistry := coreplugin.ProvideCoreRegistry(tracingService, azuremonitorService, cloudwatchService, cloudmonitoringService, elasticsearchService, graphiteService, influxdbService, lokiService, opentsdbService, prometheusService, tempoService, testdatasourceService, postgresService, mysqlService, mssqlService, grafanadsService, pyroscopeService, parcaService, zipkinService, jaegerService) + providerService := provider2.ProvideService(corepluginRegistry) + processService := process.ProvideService() orgService, err := orgimpl.ProvideService(sqlStore, cfg, quotaService) if err != nil { return nil, err @@ -1092,18 +1101,45 @@ func InitializeForTest(ctx context.Context, t sqlutil.ITestDB, testingT interfac if err != nil { return nil, err } - folderStoreImpl := folderimpl.ProvideStore(sqlStore) + apikeyService, err := apikeyimpl.ProvideService(sqlStore, cfg, quotaService) + if err != nil { + return nil, err + } + retrieverService := retriever.ProvideService(sqlStore, apikeyService, kvStore, userService, orgService) + serviceAccountPermissionsService, err := ossaccesscontrol.ProvideServiceAccountPermissions(cfg, featureToggles, routeRegisterImpl, sqlStore, accessControl, ossLicensingService, retrieverService, acimplService, teamService, userService, actionSetService) + if err != nil { + return nil, err + } + serviceAccountsService, err := manager2.ProvideServiceAccountsService(cfg, usageStats, sqlStore, apikeyService, kvStore, userService, orgService, acimplService, serviceAccountPermissionsService, serverLockService) + if err != nil { + return nil, err + } + extSvcAccountsService := extsvcaccounts.ProvideExtSvcAccountsService(acimplService, cfg, inProcBus, sqlStore, featureToggles, registerer, serviceAccountsService, secretsService, tracingService) + registryRegistry := registry2.ProvideExtSvcRegistry(cfg, extSvcAccountsService, serverLockService, featureToggles) + service13 := service3.ProvideService(sqlStore, secretsService) + serviceregistrationService := serviceregistration.ProvideService(cfg, featureToggles, registryRegistry, service13) + noop := provisionedplugins.NewNoop() + initialize := pipeline.ProvideInitializationStage(pluginManagementCfg, inMemory, providerService, processService, serviceregistrationService, acimplService, actionSetService, envVarsProvider, tracingService, noop) + terminate, err := pipeline.ProvideTerminationStage(pluginManagementCfg, inMemory, processService) + if err != nil { + return nil, err + } + errorRegistry := pluginerrs.ProvideErrorTracker() + loaderLoader := loader.ProvideService(pluginManagementCfg, discovery, bootstrap, validate, initialize, terminate, errorRegistry) + pluginstoreService, err := pluginstore.ProvideService(inMemory, sourcesService, loaderLoader, featureToggles) + if err != nil { + return nil, err + } + filestoreService := filestore.ProvideService(inMemory) + fileStoreManager := dashboards.ProvideFileStoreManager(pluginstoreService, filestoreService) tagimplService := tagimpl.ProvideService(sqlStore) dashboardsStore, err := database2.ProvideDashboardStore(sqlStore, cfg, featureToggles, tagimplService) if err != nil { return nil, err } + folderStoreImpl := folderimpl.ProvideStore(sqlStore) publicDashboardStoreImpl := database3.ProvideStore(sqlStore, cfg, featureToggles) - publicDashboardServiceWrapperImpl := service3.ProvideServiceWrapper(publicDashboardStoreImpl) - apikeyService, err := apikeyimpl.ProvideService(sqlStore, cfg, quotaService) - if err != nil { - return nil, err - } + publicDashboardServiceWrapperImpl := service4.ProvideServiceWrapper(publicDashboardStoreImpl) contextHandler := grpccontext.ProvideContextHandler(tracingService) authenticator := interceptors.ProvideAuthenticator(apikeyService, userService, acimplService, contextHandler) grpcserverProvider, err := grpcserver.ProvideService(cfg, featureToggles, authenticator, tracer, registerer) @@ -1141,7 +1177,7 @@ func InitializeForTest(ctx context.Context, t sqlutil.ITestDB, testingT interfac if err != nil { return nil, err } - cipher, err := service4.ProvideAESGCMCipherService(tracer, usageStats) + cipher, err := service5.ProvideAESGCMCipherService(tracer, usageStats) if err != nil { return nil, err } @@ -1149,7 +1185,7 @@ func InitializeForTest(ctx context.Context, t sqlutil.ITestDB, testingT interfac if err != nil { return nil, err } - encryptionManager, err := manager2.ProvideEncryptionManager(tracer, dataKeyStorage, usageStats, cipher, providerConfig) + encryptionManager, err := manager3.ProvideEncryptionManager(tracer, dataKeyStorage, usageStats, cipher, providerConfig) if err != nil { return nil, err } @@ -1170,7 +1206,7 @@ func InitializeForTest(ctx context.Context, t sqlutil.ITestDB, testingT interfac if err != nil { return nil, err } - secureValueService := service5.ProvideSecureValueService(tracer, accessClient, secureValueMetadataStorage, secureValueValidator, secureValueMutator, keeperMetadataStorage, ossKeeperService, registerer) + secureValueService := service6.ProvideSecureValueService(tracer, accessClient, secureValueMetadataStorage, secureValueValidator, secureValueMutator, keeperMetadataStorage, ossKeeperService, registerer) inlineSecureValueSupport, err := inline.ProvideInlineSecureValueService(cfg, tracer, secureValueService, accessClient) if err != nil { return nil, err @@ -1205,47 +1241,6 @@ func InitializeForTest(ctx context.Context, t sqlutil.ITestDB, testingT interfac } sortService := sort.ProvideService() folderimplService := folderimpl.ProvideService(folderStoreImpl, accessControl, inProcBus, dashboardsStore, userService, sqlStore, featureToggles, bundleregistryService, publicDashboardServiceWrapperImpl, cfg, registerer, tracer, resourceClient, dualwriteService, sortService, eventualRestConfigProvider) - searchService := searchV2.ProvideService(cfg, sqlStore, entityEventsService, acimplService, tracingService, featureToggles, orgService, userService, folderimplService) - systemUsers := store.ProvideSystemUsersService() - storageService, err := store.ProvideService(sqlStore, featureToggles, cfg, quotaService, systemUsers) - if err != nil { - return nil, err - } - grafanadsService := grafanads.ProvideService(searchService, storageService, featureToggles) - pyroscopeService := pyroscope.ProvideService(httpclientProvider) - parcaService := parca.ProvideService(httpclientProvider) - zipkinService := zipkin.ProvideService(httpclientProvider) - jaegerService := jaeger.ProvideService(httpclientProvider) - corepluginRegistry := coreplugin.ProvideCoreRegistry(tracingService, azuremonitorService, cloudwatchService, cloudmonitoringService, elasticsearchService, graphiteService, influxdbService, lokiService, opentsdbService, prometheusService, tempoService, testdatasourceService, postgresService, mysqlService, mssqlService, grafanadsService, pyroscopeService, parcaService, zipkinService, jaegerService) - providerService := provider2.ProvideService(corepluginRegistry) - processService := process.ProvideService() - retrieverService := retriever.ProvideService(sqlStore, apikeyService, kvStore, userService, orgService) - serviceAccountPermissionsService, err := ossaccesscontrol.ProvideServiceAccountPermissions(cfg, featureToggles, routeRegisterImpl, sqlStore, accessControl, ossLicensingService, retrieverService, acimplService, teamService, userService, actionSetService) - if err != nil { - return nil, err - } - serviceAccountsService, err := manager3.ProvideServiceAccountsService(cfg, usageStats, sqlStore, apikeyService, kvStore, userService, orgService, acimplService, serviceAccountPermissionsService, serverLockService) - if err != nil { - return nil, err - } - extSvcAccountsService := extsvcaccounts.ProvideExtSvcAccountsService(acimplService, cfg, inProcBus, sqlStore, featureToggles, registerer, serviceAccountsService, secretsService, tracingService) - registryRegistry := registry2.ProvideExtSvcRegistry(cfg, extSvcAccountsService, serverLockService, featureToggles) - service13 := service6.ProvideService(sqlStore, secretsService) - serviceregistrationService := serviceregistration.ProvideService(cfg, featureToggles, registryRegistry, service13) - noop := provisionedplugins.NewNoop() - initialize := pipeline.ProvideInitializationStage(pluginManagementCfg, inMemory, providerService, processService, serviceregistrationService, acimplService, actionSetService, envVarsProvider, tracingService, noop) - terminate, err := pipeline.ProvideTerminationStage(pluginManagementCfg, inMemory, processService) - if err != nil { - return nil, err - } - errorRegistry := pluginerrs.ProvideErrorTracker() - loaderLoader := loader.ProvideService(pluginManagementCfg, discovery, bootstrap, validate, initialize, terminate, errorRegistry) - pluginstoreService, err := pluginstore.ProvideService(inMemory, sourcesService, loaderLoader, featureToggles) - if err != nil { - return nil, err - } - filestoreService := filestore.ProvideService(inMemory) - fileStoreManager := dashboards.ProvideFileStoreManager(pluginstoreService, filestoreService) folderPermissionsService, err := ossaccesscontrol.ProvideFolderPermissions(cfg, featureToggles, routeRegisterImpl, sqlStore, accessControl, ossLicensingService, folderimplService, acimplService, teamService, userService, actionSetService, eventualRestConfigProvider) if err != nil { return nil, err @@ -1321,7 +1316,7 @@ func InitializeForTest(ctx context.Context, t sqlutil.ITestDB, testingT interfac azurePromMigrationService := promtypemigration.ProvideAzurePromMigrationService(service15, inMemory, repoManager, pluginInstaller, cfg) amazonPromMigrationService := promtypemigration.ProvideAmazonPromMigrationService(service15, inMemory, repoManager, pluginInstaller, cfg) promTypeMigrationProviderImpl := promtypemigration.ProvidePromTypeMigrationProvider(serverLockService, featureToggles, azurePromMigrationService, amazonPromMigrationService) - provisioningServiceImpl, err := provisioning.ProvideService(accessControl, cfg, sqlStore, pluginstoreService, dBstore, serviceService, notificationService, dashboardProvisioningService, service15, correlationsService, dashboardService, folderimplService, service13, searchService, quotaService, secretsService, orgService, receiverPermissionsService, tracingService, dualwriteService, promTypeMigrationProviderImpl, serverLockService) + provisioningServiceImpl, err := provisioning.ProvideService(accessControl, cfg, sqlStore, pluginstoreService, dBstore, serviceService, notificationService, dashboardProvisioningService, service15, correlationsService, dashboardService, folderimplService, service13, quotaService, secretsService, orgService, receiverPermissionsService, tracingService, dualwriteService, promTypeMigrationProviderImpl, serverLockService) if err != nil { return nil, err } @@ -1332,7 +1327,7 @@ func InitializeForTest(ctx context.Context, t sqlutil.ITestDB, testingT interfac oauthtokenService := oauthtoken.ProvideService(socialService, authinfoimplService, cfg, registerer, serverLockService, tracingService, userAuthTokenService, featureToggles) dataSourceProxyService := datasourceproxy.ProvideService(cacheServiceImpl, ossDataSourceRequestValidator, pluginstoreService, cfg, httpclientProvider, oauthtokenService, service15, tracingService, secretsService, featureToggles) starService := starimpl.ProvideService(sqlStore) - searchSearchService := search2.ProvideService(cfg, sqlStore, starService, dashboardService, folderimplService, featureToggles, sortService) + searchService := search2.ProvideService(cfg, sqlStore, starService, dashboardService, folderimplService, featureToggles, sortService) plugincontextProvider := plugincontext.ProvideService(cfg, cacheService, pluginstoreService, cacheServiceImpl, service15, service13, requestConfigProvider) dashboardAccessService := service7.ProvideDashboardAccessService(featureToggles, dashboardServiceImpl) grafanaLive, err := live.ProvideService(cfg, routeRegisterImpl, plugincontextProvider, pluginstoreService, middlewareHandler, cacheServiceImpl, usageStats, featureToggles, dashboardAccessService, eventualRestConfigProvider) @@ -1389,7 +1384,7 @@ func InitializeForTest(ctx context.Context, t sqlutil.ITestDB, testingT interfac secretsMigrator := migrator2.ProvideSecretsMigrator(serviceService, secretsService, sqlStore, ossImpl, featureToggles) dataSourceSecretMigrationService := migrations3.ProvideDataSourceMigrationService(service15, kvStore, featureToggles) secretMigrationProviderImpl := migrations3.ProvideSecretMigrationProvider(serverLockService, dataSourceSecretMigrationService) - publicDashboardServiceImpl := service3.ProvideService(cfg, featureToggles, publicDashboardStoreImpl, queryServiceImpl, repositoryImpl, accessControl, publicDashboardServiceWrapperImpl, dashboardService, ossLicensingService) + publicDashboardServiceImpl := service4.ProvideService(cfg, featureToggles, publicDashboardStoreImpl, queryServiceImpl, repositoryImpl, accessControl, publicDashboardServiceWrapperImpl, dashboardService, ossLicensingService) middleware := api2.ProvideMiddleware() apiApi := api2.ProvideApi(publicDashboardServiceImpl, routeRegisterImpl, accessControl, featureToggles, middleware, cfg, ossLicensingService) loginattemptimplService := loginattemptimpl.ProvideService(sqlStore, cfg, serverLockService) @@ -1399,7 +1394,6 @@ func InitializeForTest(ctx context.Context, t sqlutil.ITestDB, testingT interfac } authnService := authnimpl.ProvideAuthnService(authnimplService) navtreeService := navtreeimpl.ProvideService(cfg, accessControl, pluginstoreService, service13, starService, featureToggles, dashboardService, acimplService, kvStore, apikeyService, ossLicensingService, authnService) - searchHTTPService := searchV2.ProvideSearchHTTPService(searchService) statsService := statsimpl.ProvideService(cfg, sqlStore, dashboardService, folderimplService, orgService, resourceClient, featureToggles) gatherer := metrics.ProvideGathererForTest(registerer) apiAPI := api3.ProvideApi(cfg, featureToggles, starService, eventualRestConfigProvider) @@ -1415,7 +1409,7 @@ func InitializeForTest(ctx context.Context, t sqlutil.ITestDB, testingT interfac } idimplService := idimpl.ProvideService(cfg, localSigner, remoteCache, authnService, registerer, tracer) verifier := userimpl.ProvideVerifier(cfg, userService, tempuserService, notificationServiceMock, idimplService) - httpServer, err := api.ProvideHTTPServer(apiOpts, cfg, routeRegisterImpl, inProcBus, renderingService, ossLicensingService, hooksService, cacheService, sqlStore, ossDataSourceRequestValidator, pluginstoreService, service14, pluginstoreService, middlewareHandler, pluginerrsStore, pluginInstaller, ossImpl, cacheServiceImpl, userAuthTokenService, cleanUpService, shortURLService, queryHistoryService, correlationsService, remoteCache, provisioningServiceImpl, accessControl, dataSourceProxyService, searchSearchService, grafanaLive, gateway, plugincontextProvider, contexthandlerContextHandler, logger, featureToggles, alertNG, libraryPanelService, libraryElementService, quotaService, socialService, tracingService, serviceService, grafanaService, pluginsService, ossService, service15, queryServiceImpl, filestoreService, serviceAccountsProxy, pluginassetsService, authinfoimplService, storageService, notificationServiceMock, dashboardService, dashboardProvisioningService, folderimplService, ossProvider, serviceImpl, service13, avatarCacheServer, prefService, folderPermissionsService, dashboardPermissionsService, dashverService, starService, csrfCSRF, managedpluginsNoop, playlistService, apikeyService, kvStore, secretsMigrator, secretsService, secretMigrationProviderImpl, secretsKVStore, apiApi, userService, tempuserService, loginattemptimplService, orgService, deletionService, teamService, acimplService, navtreeService, repositoryImpl, tagimplService, searchHTTPService, oauthtokentestService, statsService, authnService, pluginscdnService, gatherer, apiAPI, registerer, eventualRestConfigProvider, anonDeviceService, verifier, preinstallImpl) + httpServer, err := api.ProvideHTTPServer(apiOpts, cfg, routeRegisterImpl, inProcBus, renderingService, ossLicensingService, hooksService, cacheService, sqlStore, ossDataSourceRequestValidator, pluginstoreService, service14, pluginstoreService, middlewareHandler, pluginerrsStore, pluginInstaller, ossImpl, cacheServiceImpl, userAuthTokenService, cleanUpService, shortURLService, queryHistoryService, correlationsService, remoteCache, provisioningServiceImpl, accessControl, dataSourceProxyService, searchService, grafanaLive, gateway, plugincontextProvider, contexthandlerContextHandler, logger, featureToggles, alertNG, libraryPanelService, libraryElementService, quotaService, socialService, tracingService, serviceService, grafanaService, pluginsService, ossService, service15, queryServiceImpl, filestoreService, serviceAccountsProxy, pluginassetsService, authinfoimplService, storageService, notificationServiceMock, dashboardService, dashboardProvisioningService, folderimplService, ossProvider, serviceImpl, service13, avatarCacheServer, prefService, folderPermissionsService, dashboardPermissionsService, dashverService, starService, csrfCSRF, managedpluginsNoop, playlistService, apikeyService, kvStore, secretsMigrator, secretsService, secretMigrationProviderImpl, secretsKVStore, apiApi, userService, tempuserService, loginattemptimplService, orgService, deletionService, teamService, acimplService, navtreeService, repositoryImpl, tagimplService, oauthtokentestService, statsService, authnService, pluginscdnService, gatherer, apiAPI, registerer, eventualRestConfigProvider, anonDeviceService, verifier, preinstallImpl) if err != nil { return nil, err } @@ -1433,6 +1427,7 @@ func InitializeForTest(ctx context.Context, t sqlutil.ITestDB, testingT interfac if err != nil { return nil, err } + entityEventsService := store.ProvideEntityEventsService(cfg, sqlStore, featureToggles) supportbundlesimplService, err := supportbundlesimpl.ProvideService(accessControl, acimplService, bundleregistryService, cfg, featureToggles, httpServer, kvStore, service13, pluginstoreService, routeRegisterImpl, ossImpl, sqlStore, usageStats, tracingService) if err != nil { return nil, err @@ -1606,7 +1601,7 @@ func InitializeForTest(ctx context.Context, t sqlutil.ITestDB, testingT interfac } ossUserProtectionImpl := authinfoimpl.ProvideOSSUserProtectionService() registration := authnimpl.ProvideRegistration(cfg, authnService, orgService, userAuthTokenService, acimplService, permissionRegistry, apikeyService, userService, authService, ossUserProtectionImpl, loginattemptimplService, quotaService, authinfoimplService, renderingService, featureToggles, oauthtokentestService, socialService, remoteCache, ldapImpl, ossImpl, tracingService, tempuserService, notificationServiceMock) - backgroundServiceRegistry := backgroundsvcs.ProvideBackgroundServiceRegistry(httpServer, alertNG, cleanUpService, grafanaLive, gateway, notificationService, pluginstoreService, renderingService, userAuthTokenService, tracingService, provisioningServiceImpl, usageStats, statscollectorService, grafanaService, pluginsService, internalMetricsService, secretsService, remoteCache, storageService, searchService, entityEventsService, serviceAccountsService, grpcserverProvider, secretMigrationProviderImpl, loginattemptimplService, supportbundlesimplService, metricService, keyRetriever, angulardetectorsproviderDynamic, apiserverService, anonDeviceService, ssosettingsimplService, pluginexternalService, plugininstallerService, zanzanaReconciler, appregistryService, dashboardUpdater, dashboardServiceImpl, worker, fixedRolesLoader, syncer, serviceImpl, serviceAccountsProxy, healthService, reflectionService, apiService, apiregistryService, idimplService, teamAPI, ssosettingsimplService, cloudmigrationService, registration) + backgroundServiceRegistry := backgroundsvcs.ProvideBackgroundServiceRegistry(httpServer, alertNG, cleanUpService, grafanaLive, gateway, notificationService, pluginstoreService, renderingService, userAuthTokenService, tracingService, provisioningServiceImpl, usageStats, statscollectorService, grafanaService, pluginsService, internalMetricsService, secretsService, remoteCache, storageService, entityEventsService, serviceAccountsService, grpcserverProvider, secretMigrationProviderImpl, loginattemptimplService, supportbundlesimplService, metricService, keyRetriever, angulardetectorsproviderDynamic, apiserverService, anonDeviceService, ssosettingsimplService, pluginexternalService, plugininstallerService, zanzanaReconciler, appregistryService, dashboardUpdater, dashboardServiceImpl, worker, fixedRolesLoader, syncer, serviceImpl, serviceAccountsProxy, healthService, reflectionService, apiService, apiregistryService, idimplService, teamAPI, ssosettingsimplService, cloudmigrationService, registration) usageStatsProvidersRegistry := usagestatssvcs.ProvideUsageStatsProvidersRegistry(acimplService, userService) server, err := New(opts, cfg, httpServer, acimplService, provisioningServiceImpl, backgroundServiceRegistry, usageStatsProvidersRegistry, statscollectorService, tracingService, featureToggles, registerer) if err != nil { @@ -1697,7 +1692,7 @@ func InitializeForCLI(ctx context.Context, cfg *setting.Cfg) (Runner, error) { if err != nil { return Runner{}, err } - cipher, err := service4.ProvideAESGCMCipherService(tracer, usageStats) + cipher, err := service5.ProvideAESGCMCipherService(tracer, usageStats) if err != nil { return Runner{}, err } @@ -1705,11 +1700,11 @@ func InitializeForCLI(ctx context.Context, cfg *setting.Cfg) (Runner, error) { if err != nil { return Runner{}, err } - encryptionManager, err := manager2.ProvideEncryptionManager(tracer, dataKeyStorage, usageStats, cipher, providerConfig) + encryptionManager, err := manager3.ProvideEncryptionManager(tracer, dataKeyStorage, usageStats, cipher, providerConfig) if err != nil { return Runner{}, err } - consolidationService := service5.ProvideConsolidationService(tracer, globalDataKeyStorage, encryptedValueStorage, globalEncryptedValueStorage, encryptionManager) + consolidationService := service6.ProvideConsolidationService(tracer, globalDataKeyStorage, encryptedValueStorage, globalEncryptedValueStorage, encryptionManager) runner := NewRunner(cfg, sqlStore, ossImpl, serviceService, featureToggles, secretsService, secretsMigrator, userService, consolidationService) return runner, nil } @@ -1802,7 +1797,7 @@ var withOTelSet = wire.NewSet( otelTracer, grpcserver.ProvideService, interceptors.ProvideAuthenticator, ) -var wireBasicSet = wire.NewSet(annotationsimpl.ProvideService, wire.Bind(new(annotations.Repository), new(*annotationsimpl.RepositoryImpl)), New, api.ProvideHTTPServer, query.ProvideService, wire.Bind(new(query.Service), new(*query.ServiceImpl)), bus.ProvideBus, wire.Bind(new(bus.Bus), new(*bus.InProcBus)), rendering.ProvideService, wire.Bind(new(rendering.Service), new(*rendering.RenderingService)), routing.ProvideRegister, wire.Bind(new(routing.RouteRegister), new(*routing.RouteRegisterImpl)), hooks.ProvideService, kvstore.ProvideService, localcache.ProvideService, bundleregistry.ProvideService, wire.Bind(new(supportbundles.Service), new(*bundleregistry.Service)), updatemanager.ProvideGrafanaService, updatemanager.ProvidePluginsService, service.ProvideService, wire.Bind(new(usagestats.Service), new(*service.UsageStats)), validator3.ProvideService, provisioning.ProvideStubProvisioningService, legacy.ProvideMigratorDashboardAccessor, migrations2.ProvideUnifiedMigrator, pluginsintegration.WireSet, dashboards.ProvideFileStoreManager, wire.Bind(new(dashboards.FileStore), new(*dashboards.FileStoreManager)), cloudwatch.ProvideService, cloudmonitoring.ProvideService, azuremonitor.ProvideService, postgres.ProvideService, mysql.ProvideService, mssql.ProvideService, store.ProvideEntityEventsService, dualwrite.ProvideService, httpclientprovider.New, wire.Bind(new(httpclient.Provider), new(*httpclient2.Provider)), serverlock.ProvideService, wire.Bind(new(installsync.ServerLock), new(*serverlock.ServerLockService)), annotationsimpl.ProvideCleanupService, wire.Bind(new(annotations.Cleaner), new(*annotationsimpl.CleanupServiceImpl)), cleanup.ProvideService, shorturlimpl.ProvideService, wire.Bind(new(shorturls.Service), new(*shorturlimpl.ShortURLService)), queryhistory.ProvideService, wire.Bind(new(queryhistory.Service), new(*queryhistory.QueryHistoryService)), correlations.ProvideService, wire.Bind(new(correlations.Service), new(*correlations.CorrelationsService)), quotaimpl.ProvideService, remotecache.ProvideService, wire.Bind(new(remotecache.CacheStorage), new(*remotecache.RemoteCache)), authinfoimpl.ProvideService, wire.Bind(new(login.AuthInfoService), new(*authinfoimpl.Service)), authinfoimpl.ProvideStore, datasourceproxy.ProvideService, sort.ProvideService, search2.ProvideService, searchV2.ProvideService, searchV2.ProvideSearchHTTPService, store.ProvideService, store.ProvideSystemUsersService, live.ProvideService, live.ProvideDashboardActivityChannel, pushhttp.ProvideService, contexthandler.ProvideService, service12.ProvideService, wire.Bind(new(service12.LDAP), new(*service12.LDAPImpl)), jwt.ProvideService, wire.Bind(new(jwt.JWTService), new(*jwt.AuthService)), store2.ProvideDBStore, image.ProvideDeleteExpiredService, ngalert.ProvideService, librarypanels.ProvideService, wire.Bind(new(librarypanels.Service), new(*librarypanels.LibraryPanelService)), libraryelements.ProvideService, wire.Bind(new(libraryelements.Service), new(*libraryelements.LibraryElementService)), notifications.ProvideService, notifications.ProvideSmtpService, github.ProvideFactory, tracing.ProvideService, tracing.ProvideTracingConfig, wire.Bind(new(tracing.Tracer), new(*tracing.TracingService)), withOTelSet, testdatasource.ProvideService, api4.ProvideService, opentsdb.ProvideService, socialimpl.ProvideService, influxdb.ProvideService, wire.Bind(new(social.Service), new(*socialimpl.SocialService)), tempo.ProvideService, loki.ProvideService, graphite.ProvideService, prometheus.ProvideService, elasticsearch.ProvideService, pyroscope.ProvideService, parca.ProvideService, zipkin.ProvideService, jaeger.ProvideService, service9.ProvideCacheService, wire.Bind(new(datasources.CacheService), new(*service9.CacheServiceImpl)), service2.ProvideEncryptionService, wire.Bind(new(encryption2.Internal), new(*service2.Service)), manager.ProvideSecretsService, wire.Bind(new(secrets.Service), new(*manager.SecretsService)), database.ProvideSecretsStore, wire.Bind(new(secrets.Store), new(*database.SecretsStoreImpl)), garbagecollectionworker.ProvideWorker, grafanads.ProvideService, wire.Bind(new(dashboardsnapshots.Store), new(*database5.DashboardSnapshotStore)), database5.ProvideStore, wire.Bind(new(dashboardsnapshots.Service), new(*service10.ServiceImpl)), service10.ProvideService, service9.ProvideService, wire.Bind(new(datasources.DataSourceService), new(*service9.Service)), service9.ProvideLegacyDataSourceLookup, retriever.ProvideService, wire.Bind(new(serviceaccounts.ServiceAccountRetriever), new(*retriever.Service)), ossaccesscontrol.ProvideServiceAccountPermissions, wire.Bind(new(accesscontrol.ServiceAccountPermissionsService), new(*ossaccesscontrol.ServiceAccountPermissionsService)), manager3.ProvideServiceAccountsService, proxy.ProvideServiceAccountsProxy, wire.Bind(new(serviceaccounts.Service), new(*proxy.ServiceAccountsProxy)), dsquerierclient.NewNullQSDatasourceClientBuilder, expr.ProvideService, featuremgmt.ProvideManagerService, featuremgmt.ProvideToggles, service7.ProvideDashboardServiceImpl, wire.Bind(new(dashboards2.PermissionsRegistrationService), new(*service7.DashboardServiceImpl)), service7.ProvideDashboardService, service7.ProvideDashboardProvisioningService, service7.ProvideDashboardPluginService, service7.ProvideDashboardAccessService, database2.ProvideDashboardStore, folderimpl.ProvideService, wire.Bind(new(folder.Service), new(*folderimpl.Service)), wire.Bind(new(folder.LegacyService), new(*folderimpl.Service)), folderimpl.ProvideStore, wire.Bind(new(folder.Store), new(*folderimpl.FolderStoreImpl)), service11.ProvideService, wire.Bind(new(dashboardimport.Service), new(*service11.ImportDashboardService)), service8.ProvideService, wire.Bind(new(plugindashboards.Service), new(*service8.Service)), service8.ProvideDashboardUpdater, kvstore2.ProvideService, avatar.ProvideAvatarCacheServer, statscollector.ProvideService, csrf.ProvideCSRFFilter, wire.Bind(new(csrf.Service), new(*csrf.CSRF)), ossaccesscontrol.ProvideTeamPermissions, wire.Bind(new(accesscontrol.TeamPermissionsService), new(*ossaccesscontrol.TeamPermissionsService)), ossaccesscontrol.ProvideFolderPermissions, wire.Bind(new(accesscontrol.FolderPermissionsService), new(*ossaccesscontrol.FolderPermissionsService)), ossaccesscontrol.ProvideDashboardPermissions, wire.Bind(new(accesscontrol.DashboardPermissionsService), new(*ossaccesscontrol.DashboardPermissionsService)), ossaccesscontrol.ProvideReceiverPermissionsService, wire.Bind(new(accesscontrol.ReceiverPermissionsService), new(*ossaccesscontrol.ReceiverPermissionsService)), starimpl.ProvideService, playlistimpl.ProvideService, apikeyimpl.ProvideService, dashverimpl.ProvideService, service3.ProvideService, wire.Bind(new(publicdashboards.Service), new(*service3.PublicDashboardServiceImpl)), database3.ProvideStore, wire.Bind(new(publicdashboards.Store), new(*database3.PublicDashboardStoreImpl)), metric.ProvideService, api2.ProvideApi, api3.ProvideApi, userimpl.ProvideService, orgimpl.ProvideService, orgimpl.ProvideDeletionService, statsimpl.ProvideService, grpccontext.ProvideContextHandler, grpcserver.ProvideHealthService, grpcserver.ProvideReflectionService, resolver.ProvideEntityReferenceResolver, teamimpl.ProvideService, teamapi.ProvideTeamAPI, tempuserimpl.ProvideService, loginattemptimpl.ProvideService, wire.Bind(new(loginattempt.Service), new(*loginattemptimpl.Service)), migrations3.ProvideDataSourceMigrationService, migrations3.ProvideSecretMigrationProvider, wire.Bind(new(migrations3.SecretMigrationProvider), new(*migrations3.SecretMigrationProviderImpl)), promtypemigration.ProvideAzurePromMigrationService, promtypemigration.ProvideAmazonPromMigrationService, promtypemigration.ProvidePromTypeMigrationProvider, wire.Bind(new(promtypemigration.PromTypeMigrationProvider), new(*promtypemigration.PromTypeMigrationProviderImpl)), resourcepermissions.NewActionSetService, wire.Bind(new(accesscontrol.ActionResolver), new(resourcepermissions.ActionSetService)), wire.Bind(new(pluginaccesscontrol.ActionSetRegistry), new(resourcepermissions.ActionSetService)), permreg.ProvidePermissionRegistry, acimpl.ProvideAccessControl, accesscontrol.ProvideFixedRolesLoader, dualwrite2.ProvideZanzanaReconciler, navtreeimpl.ProvideService, wire.Bind(new(accesscontrol.AccessControl), new(*acimpl.AccessControl)), wire.Bind(new(notifications.TempUserStore), new(tempuser.Service)), tagimpl.ProvideService, wire.Bind(new(tag.Service), new(*tagimpl.Service)), authnimpl.ProvideService, authnimpl.ProvideIdentitySynchronizer, authnimpl.ProvideAuthnService, authnimpl.ProvideAuthnServiceAuthenticateOnly, authnimpl.ProvideRegistration, supportbundlesimpl.ProvideService, extsvcaccounts.ProvideExtSvcAccountsService, wire.Bind(new(serviceaccounts.ExtSvcAccountsService), new(*extsvcaccounts.ExtSvcAccountsService)), registry2.ProvideExtSvcRegistry, wire.Bind(new(extsvcauth.ExternalServiceRegistry), new(*registry2.Registry)), anonstore.ProvideAnonDBStore, wire.Bind(new(anonstore.AnonStore), new(*anonstore.AnonDBStore)), loggermw.Provide, slogadapter.Provide, signingkeysimpl.ProvideEmbeddedSigningKeysService, wire.Bind(new(signingkeys.Service), new(*signingkeysimpl.Service)), ssosettingsimpl.ProvideService, wire.Bind(new(ssosettings.Service), new(*ssosettingsimpl.Service)), idimpl.ProvideService, wire.Bind(new(auth.IDService), new(*idimpl.Service)), cloudmigrationimpl.ProvideService, caching.ProvideCachingServiceClient, userimpl.ProvideVerifier, connectors.ProvideOrgRoleMapper, wire.Bind(new(user.Verifier), new(*userimpl.Verifier)), authz.WireSet, metadata.ProvideSecureValueMetadataStorage, metadata.ProvideKeeperMetadataStorage, metadata.ProvideDecryptStorage, decrypt.ProvideDecryptAuthorizer, wire.Value([]decrypt.ExtraOwnerDecrypter(nil)), decrypt.ProvideDecryptService, inline.ProvideInlineSecureValueService, encryption.ProvideDataKeyStorage, encryption.ProvideGlobalDataKeyStorage, encryption.ProvideEncryptedValueStorage, encryption.ProvideGlobalEncryptedValueStorage, encryption.ProvideEncryptedValueMigrationExecutor, service5.ProvideSecureValueService, validator.ProvideKeeperValidator, validator.ProvideSecureValueValidator, mutator.ProvideKeeperMutator, mutator.ProvideSecureValueMutator, migrator.NewWithEngine, database4.ProvideDatabase, clock.ProvideClock, wire.Bind(new(contracts.Database), new(*database4.Database)), wire.Bind(new(contracts.Clock), new(*clock.Clock)), manager2.ProvideEncryptionManager, service4.ProvideAESGCMCipherService, resource.ProvideStorageMetrics, resource.ProvideIndexMetrics, migrations2.ProvideUnifiedStorageMigrationService, apiserver.WireSet, apiregistry.WireSet, appregistry.WireSet, client.ProvideK8sClientWithFallback) +var wireBasicSet = wire.NewSet(annotationsimpl.ProvideService, wire.Bind(new(annotations.Repository), new(*annotationsimpl.RepositoryImpl)), New, api.ProvideHTTPServer, query.ProvideService, wire.Bind(new(query.Service), new(*query.ServiceImpl)), bus.ProvideBus, wire.Bind(new(bus.Bus), new(*bus.InProcBus)), rendering.ProvideService, wire.Bind(new(rendering.Service), new(*rendering.RenderingService)), routing.ProvideRegister, wire.Bind(new(routing.RouteRegister), new(*routing.RouteRegisterImpl)), hooks.ProvideService, kvstore.ProvideService, localcache.ProvideService, bundleregistry.ProvideService, wire.Bind(new(supportbundles.Service), new(*bundleregistry.Service)), updatemanager.ProvideGrafanaService, updatemanager.ProvidePluginsService, service.ProvideService, wire.Bind(new(usagestats.Service), new(*service.UsageStats)), validator3.ProvideService, provisioning.ProvideStubProvisioningService, legacy.ProvideMigratorDashboardAccessor, migrations2.ProvideUnifiedMigrator, pluginsintegration.WireSet, dashboards.ProvideFileStoreManager, wire.Bind(new(dashboards.FileStore), new(*dashboards.FileStoreManager)), cloudwatch.ProvideService, cloudmonitoring.ProvideService, azuremonitor.ProvideService, postgres.ProvideService, mysql.ProvideService, mssql.ProvideService, store.ProvideEntityEventsService, dualwrite.ProvideService, httpclientprovider.New, wire.Bind(new(httpclient.Provider), new(*httpclient2.Provider)), serverlock.ProvideService, wire.Bind(new(installsync.ServerLock), new(*serverlock.ServerLockService)), annotationsimpl.ProvideCleanupService, wire.Bind(new(annotations.Cleaner), new(*annotationsimpl.CleanupServiceImpl)), cleanup.ProvideService, shorturlimpl.ProvideService, wire.Bind(new(shorturls.Service), new(*shorturlimpl.ShortURLService)), queryhistory.ProvideService, wire.Bind(new(queryhistory.Service), new(*queryhistory.QueryHistoryService)), correlations.ProvideService, wire.Bind(new(correlations.Service), new(*correlations.CorrelationsService)), quotaimpl.ProvideService, remotecache.ProvideService, wire.Bind(new(remotecache.CacheStorage), new(*remotecache.RemoteCache)), authinfoimpl.ProvideService, wire.Bind(new(login.AuthInfoService), new(*authinfoimpl.Service)), authinfoimpl.ProvideStore, datasourceproxy.ProvideService, sort.ProvideService, search2.ProvideService, store.ProvideService, store.ProvideSystemUsersService, live.ProvideService, live.ProvideDashboardActivityChannel, pushhttp.ProvideService, contexthandler.ProvideService, service12.ProvideService, wire.Bind(new(service12.LDAP), new(*service12.LDAPImpl)), jwt.ProvideService, wire.Bind(new(jwt.JWTService), new(*jwt.AuthService)), store2.ProvideDBStore, image.ProvideDeleteExpiredService, ngalert.ProvideService, librarypanels.ProvideService, wire.Bind(new(librarypanels.Service), new(*librarypanels.LibraryPanelService)), libraryelements.ProvideService, wire.Bind(new(libraryelements.Service), new(*libraryelements.LibraryElementService)), notifications.ProvideService, notifications.ProvideSmtpService, github.ProvideFactory, tracing.ProvideService, tracing.ProvideTracingConfig, wire.Bind(new(tracing.Tracer), new(*tracing.TracingService)), withOTelSet, testdatasource.ProvideService, api4.ProvideService, opentsdb.ProvideService, socialimpl.ProvideService, influxdb.ProvideService, wire.Bind(new(social.Service), new(*socialimpl.SocialService)), tempo.ProvideService, loki.ProvideService, graphite.ProvideService, prometheus.ProvideService, elasticsearch.ProvideService, pyroscope.ProvideService, parca.ProvideService, zipkin.ProvideService, jaeger.ProvideService, service9.ProvideCacheService, wire.Bind(new(datasources.CacheService), new(*service9.CacheServiceImpl)), service2.ProvideEncryptionService, wire.Bind(new(encryption2.Internal), new(*service2.Service)), manager.ProvideSecretsService, wire.Bind(new(secrets.Service), new(*manager.SecretsService)), database.ProvideSecretsStore, wire.Bind(new(secrets.Store), new(*database.SecretsStoreImpl)), garbagecollectionworker.ProvideWorker, grafanads.ProvideService, wire.Bind(new(dashboardsnapshots.Store), new(*database5.DashboardSnapshotStore)), database5.ProvideStore, wire.Bind(new(dashboardsnapshots.Service), new(*service10.ServiceImpl)), service10.ProvideService, service9.ProvideService, wire.Bind(new(datasources.DataSourceService), new(*service9.Service)), service9.ProvideLegacyDataSourceLookup, retriever.ProvideService, wire.Bind(new(serviceaccounts.ServiceAccountRetriever), new(*retriever.Service)), ossaccesscontrol.ProvideServiceAccountPermissions, wire.Bind(new(accesscontrol.ServiceAccountPermissionsService), new(*ossaccesscontrol.ServiceAccountPermissionsService)), manager2.ProvideServiceAccountsService, proxy.ProvideServiceAccountsProxy, wire.Bind(new(serviceaccounts.Service), new(*proxy.ServiceAccountsProxy)), dsquerierclient.NewNullQSDatasourceClientBuilder, expr.ProvideService, featuremgmt.ProvideManagerService, featuremgmt.ProvideToggles, service7.ProvideDashboardServiceImpl, wire.Bind(new(dashboards2.PermissionsRegistrationService), new(*service7.DashboardServiceImpl)), service7.ProvideDashboardService, service7.ProvideDashboardProvisioningService, service7.ProvideDashboardPluginService, service7.ProvideDashboardAccessService, database2.ProvideDashboardStore, folderimpl.ProvideService, wire.Bind(new(folder.Service), new(*folderimpl.Service)), wire.Bind(new(folder.LegacyService), new(*folderimpl.Service)), folderimpl.ProvideStore, wire.Bind(new(folder.Store), new(*folderimpl.FolderStoreImpl)), service11.ProvideService, wire.Bind(new(dashboardimport.Service), new(*service11.ImportDashboardService)), service8.ProvideService, wire.Bind(new(plugindashboards.Service), new(*service8.Service)), service8.ProvideDashboardUpdater, kvstore2.ProvideService, avatar.ProvideAvatarCacheServer, statscollector.ProvideService, csrf.ProvideCSRFFilter, wire.Bind(new(csrf.Service), new(*csrf.CSRF)), ossaccesscontrol.ProvideTeamPermissions, wire.Bind(new(accesscontrol.TeamPermissionsService), new(*ossaccesscontrol.TeamPermissionsService)), ossaccesscontrol.ProvideFolderPermissions, wire.Bind(new(accesscontrol.FolderPermissionsService), new(*ossaccesscontrol.FolderPermissionsService)), ossaccesscontrol.ProvideDashboardPermissions, wire.Bind(new(accesscontrol.DashboardPermissionsService), new(*ossaccesscontrol.DashboardPermissionsService)), ossaccesscontrol.ProvideReceiverPermissionsService, wire.Bind(new(accesscontrol.ReceiverPermissionsService), new(*ossaccesscontrol.ReceiverPermissionsService)), starimpl.ProvideService, playlistimpl.ProvideService, apikeyimpl.ProvideService, dashverimpl.ProvideService, service4.ProvideService, wire.Bind(new(publicdashboards.Service), new(*service4.PublicDashboardServiceImpl)), database3.ProvideStore, wire.Bind(new(publicdashboards.Store), new(*database3.PublicDashboardStoreImpl)), metric.ProvideService, api2.ProvideApi, api3.ProvideApi, userimpl.ProvideService, orgimpl.ProvideService, orgimpl.ProvideDeletionService, statsimpl.ProvideService, grpccontext.ProvideContextHandler, grpcserver.ProvideHealthService, grpcserver.ProvideReflectionService, resolver.ProvideEntityReferenceResolver, teamimpl.ProvideService, teamapi.ProvideTeamAPI, tempuserimpl.ProvideService, loginattemptimpl.ProvideService, wire.Bind(new(loginattempt.Service), new(*loginattemptimpl.Service)), migrations3.ProvideDataSourceMigrationService, migrations3.ProvideSecretMigrationProvider, wire.Bind(new(migrations3.SecretMigrationProvider), new(*migrations3.SecretMigrationProviderImpl)), promtypemigration.ProvideAzurePromMigrationService, promtypemigration.ProvideAmazonPromMigrationService, promtypemigration.ProvidePromTypeMigrationProvider, wire.Bind(new(promtypemigration.PromTypeMigrationProvider), new(*promtypemigration.PromTypeMigrationProviderImpl)), resourcepermissions.NewActionSetService, wire.Bind(new(accesscontrol.ActionResolver), new(resourcepermissions.ActionSetService)), wire.Bind(new(pluginaccesscontrol.ActionSetRegistry), new(resourcepermissions.ActionSetService)), permreg.ProvidePermissionRegistry, acimpl.ProvideAccessControl, accesscontrol.ProvideFixedRolesLoader, dualwrite2.ProvideZanzanaReconciler, navtreeimpl.ProvideService, wire.Bind(new(accesscontrol.AccessControl), new(*acimpl.AccessControl)), wire.Bind(new(notifications.TempUserStore), new(tempuser.Service)), tagimpl.ProvideService, wire.Bind(new(tag.Service), new(*tagimpl.Service)), authnimpl.ProvideService, authnimpl.ProvideIdentitySynchronizer, authnimpl.ProvideAuthnService, authnimpl.ProvideAuthnServiceAuthenticateOnly, authnimpl.ProvideRegistration, supportbundlesimpl.ProvideService, extsvcaccounts.ProvideExtSvcAccountsService, wire.Bind(new(serviceaccounts.ExtSvcAccountsService), new(*extsvcaccounts.ExtSvcAccountsService)), registry2.ProvideExtSvcRegistry, wire.Bind(new(extsvcauth.ExternalServiceRegistry), new(*registry2.Registry)), anonstore.ProvideAnonDBStore, wire.Bind(new(anonstore.AnonStore), new(*anonstore.AnonDBStore)), loggermw.Provide, slogadapter.Provide, signingkeysimpl.ProvideEmbeddedSigningKeysService, wire.Bind(new(signingkeys.Service), new(*signingkeysimpl.Service)), ssosettingsimpl.ProvideService, wire.Bind(new(ssosettings.Service), new(*ssosettingsimpl.Service)), idimpl.ProvideService, wire.Bind(new(auth.IDService), new(*idimpl.Service)), cloudmigrationimpl.ProvideService, caching.ProvideCachingServiceClient, userimpl.ProvideVerifier, connectors.ProvideOrgRoleMapper, wire.Bind(new(user.Verifier), new(*userimpl.Verifier)), authz.WireSet, metadata.ProvideSecureValueMetadataStorage, metadata.ProvideKeeperMetadataStorage, metadata.ProvideDecryptStorage, decrypt.ProvideDecryptAuthorizer, wire.Value([]decrypt.ExtraOwnerDecrypter(nil)), decrypt.ProvideDecryptService, inline.ProvideInlineSecureValueService, encryption.ProvideDataKeyStorage, encryption.ProvideGlobalDataKeyStorage, encryption.ProvideEncryptedValueStorage, encryption.ProvideGlobalEncryptedValueStorage, encryption.ProvideEncryptedValueMigrationExecutor, service6.ProvideSecureValueService, validator.ProvideKeeperValidator, validator.ProvideSecureValueValidator, mutator.ProvideKeeperMutator, mutator.ProvideSecureValueMutator, migrator.NewWithEngine, database4.ProvideDatabase, clock.ProvideClock, wire.Bind(new(contracts.Database), new(*database4.Database)), wire.Bind(new(contracts.Clock), new(*clock.Clock)), manager3.ProvideEncryptionManager, service5.ProvideAESGCMCipherService, resource.ProvideStorageMetrics, resource.ProvideIndexMetrics, migrations2.ProvideUnifiedStorageMigrationService, apiserver.WireSet, apiregistry.WireSet, appregistry.WireSet, client.ProvideK8sClientWithFallback) var wireSet = wire.NewSet( wireBasicSet, metrics.WireSet, sqlstore.ProvideService, metrics2.ProvideService, wire.Bind(new(notifications.Service), new(*notifications.NotificationService)), wire.Bind(new(notifications.WebhookSender), new(*notifications.NotificationService)), wire.Bind(new(notifications.EmailSender), new(*notifications.NotificationService)), wire.Bind(new(db.DB), new(*sqlstore.SQLStore)), prefimpl.ProvideService, oauthtoken.ProvideService, wire.Bind(new(oauthtoken.OAuthTokenService), new(*oauthtoken.Service)), wire.Bind(new(cleanup.AlertRuleService), new(*store2.DBstore)), diff --git a/pkg/services/pluginsintegration/plugintest/plugins_test.go b/pkg/services/pluginsintegration/plugintest/plugins_test.go index df4a0fd7b75..9c5230a96c5 100644 --- a/pkg/services/pluginsintegration/plugintest/plugins_test.go +++ b/pkg/services/pluginsintegration/plugintest/plugins_test.go @@ -15,7 +15,6 @@ import ( "github.com/grafana/grafana-plugin-sdk-go/backend" "github.com/grafana/grafana-plugin-sdk-go/backend/httpclient" - "github.com/grafana/grafana/pkg/infra/db" "github.com/grafana/grafana/pkg/infra/fs" "github.com/grafana/grafana/pkg/infra/tracing" "github.com/grafana/grafana/pkg/plugins" @@ -24,8 +23,6 @@ import ( "github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/services/pluginsintegration" "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore" - "github.com/grafana/grafana/pkg/services/searchV2" - "github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/tests/testinfra" "github.com/grafana/grafana/pkg/tests/testsuite" @@ -164,9 +161,7 @@ func TestIntegrationPluginManager(t *testing.T) { pg := postgres.ProvideService() my := mysql.ProvideService() ms := mssql.ProvideService(cfg) - db := db.InitTestDB(t, sqlstore.InitTestDBOpt{Cfg: cfg}) - sv2 := searchV2.ProvideService(cfg, db, nil, nil, tracer, features, nil, nil, nil) - graf := grafanads.ProvideService(sv2, nil, features) + graf := grafanads.ProvideService(nil, features) pyroscope := pyroscope.ProvideService(hcp) parca := parca.ProvideService(hcp) zipkin := zipkin.ProvideService(hcp) diff --git a/pkg/services/provisioning/provisioning.go b/pkg/services/provisioning/provisioning.go index bc7c53e0cb2..24f9802188c 100644 --- a/pkg/services/provisioning/provisioning.go +++ b/pkg/services/provisioning/provisioning.go @@ -35,7 +35,6 @@ import ( "github.com/grafana/grafana/pkg/services/provisioning/datasources" "github.com/grafana/grafana/pkg/services/provisioning/plugins" "github.com/grafana/grafana/pkg/services/quota" - "github.com/grafana/grafana/pkg/services/searchV2" "github.com/grafana/grafana/pkg/services/secrets" "github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/storage/legacysql/dualwrite" @@ -57,7 +56,6 @@ func ProvideService( dashboardService dashboardservice.DashboardService, folderService folder.Service, pluginSettings pluginsettings.Service, - searchService searchV2.SearchService, quotaService quota.Service, secrectService secrets.Service, orgService org.Service, @@ -84,7 +82,6 @@ func ProvideService( datasourceService: datasourceService, correlationsService: correlationsService, pluginsSettings: pluginSettings, - searchService: searchService, quotaService: quotaService, secretService: secrectService, log: log.New("provisioning"), @@ -138,9 +135,6 @@ func (ps *ProvisioningServiceImpl) starting(ctx context.Context) error { return err } } - if ps.dashboardProvisioner.HasDashboardSources() { - ps.searchService.TriggerReIndex() - } return nil } @@ -194,7 +188,6 @@ func newProvisioningServiceImpl( provisionDatasources func(context.Context, string, datasources.BaseDataSourceService, datasources.CorrelationsStore, org.Service) error, provisionPlugins func(context.Context, string, pluginstore.Store, pluginsettings.Service, org.Service) error, migratePrometheusType func(context.Context) error, - searchService searchV2.SearchService, ) (*ProvisioningServiceImpl, error) { s := &ProvisioningServiceImpl{ log: log.New("provisioning"), @@ -202,7 +195,6 @@ func newProvisioningServiceImpl( provisionDatasources: provisionDatasources, provisionPlugins: provisionPlugins, Cfg: setting.NewCfg(), - searchService: searchService, migratePrometheusType: migratePrometheusType, } @@ -238,7 +230,6 @@ type ProvisioningServiceImpl struct { datasourceService datasourceservice.DataSourceService correlationsService correlations.Service pluginsSettings pluginsettings.Service - searchService searchV2.SearchService quotaService quota.Service secretService secrets.Service folderService folder.Service diff --git a/pkg/services/provisioning/provisioning_test.go b/pkg/services/provisioning/provisioning_test.go index b94d7beac37..b6f4c1e7f84 100644 --- a/pkg/services/provisioning/provisioning_test.go +++ b/pkg/services/provisioning/provisioning_test.go @@ -20,7 +20,6 @@ import ( "github.com/grafana/grafana/pkg/services/provisioning/dashboards" "github.com/grafana/grafana/pkg/services/provisioning/datasources" "github.com/grafana/grafana/pkg/services/provisioning/utils" - "github.com/grafana/grafana/pkg/services/searchV2" "github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/storage/legacysql/dualwrite" ) @@ -159,8 +158,6 @@ func setup(t *testing.T) *serviceTestStruct { pollChangesChannel <- ctx } - searchStub := searchV2.NewStubSearchService() - service, err := newProvisioningServiceImpl( func(context.Context, string, dashboardstore.DashboardProvisioningService, *setting.Cfg, org.Service, utils.DashboardStore, folder.Service, dualwrite.Service, *serverlock.ServerLockService) (dashboards.DashboardProvisioner, error) { serviceTest.dashboardProvisionerInstantiations++ @@ -175,7 +172,6 @@ func setup(t *testing.T) *serviceTestStruct { func(context.Context) error { return nil }, - searchStub, ) service.provisionAlerting = func(context.Context, prov_alerting.ProvisionerConfig) error { return nil diff --git a/pkg/services/searchV2/allowed_actions.go b/pkg/services/searchV2/allowed_actions.go deleted file mode 100644 index 591550331aa..00000000000 --- a/pkg/services/searchV2/allowed_actions.go +++ /dev/null @@ -1,255 +0,0 @@ -package searchV2 - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "sort" - - "github.com/grafana/grafana-plugin-sdk-go/backend" - "github.com/grafana/grafana-plugin-sdk-go/data" - - "github.com/grafana/grafana/pkg/services/accesscontrol" - "github.com/grafana/grafana/pkg/services/dashboards" - "github.com/grafana/grafana/pkg/services/datasources" - "github.com/grafana/grafana/pkg/services/user" -) - -func (s *StandardSearchService) addAllowedActionsField(ctx context.Context, orgId int64, user *user.SignedInUser, response *backend.DataResponse) error { - references, err := getEntityReferences(response) - if err != nil { - return err - } - - allAllowedActions, err := s.createAllowedActions(ctx, orgId, user, references) - if err != nil { - return err - } - - if len(response.Frames) == 0 { - return errors.New("empty response") - } - - frame := response.Frames[0] - - allowedActionsField := data.NewFieldFromFieldType(data.FieldTypeJSON, len(allAllowedActions)) - allowedActionsField.Name = "allowed_actions" - frame.Fields = append(frame.Fields, allowedActionsField) - - for i, actions := range allAllowedActions { - js, _ := json.Marshal(actions) - jsb := json.RawMessage(js) - allowedActionsField.Set(i, jsb) - } - - return nil -} - -type allowedActions struct { - EntityKind entityKind `json:"kind"` - UID string `json:"uid"` - Actions []string `json:"actions"` -} - -func (s *StandardSearchService) createAllowedActions(ctx context.Context, orgId int64, user *user.SignedInUser, references []entityReferences) ([][]allowedActions, error) { - uidsPerKind := make(map[entityKind][]string) - for _, refs := range references { - if _, ok := uidsPerKind[refs.entityKind]; !ok { - uidsPerKind[refs.entityKind] = []string{} - } - - uidsPerKind[refs.entityKind] = append(uidsPerKind[refs.entityKind], refs.uid) - - if len(refs.dsUids) > 0 { - if _, ok := uidsPerKind[entityKindDatasource]; !ok { - uidsPerKind[entityKindDatasource] = []string{} - } - - uidsPerKind[entityKindDatasource] = append(uidsPerKind[entityKindDatasource], refs.dsUids...) - } - } - - allowedActionsByUid := make(map[entityKind]map[string][]string) - - for entKind, uids := range uidsPerKind { - if entKind == entityKindPanel { - emptyAllowedActions := make(map[string][]string) - for _, uid := range uids { - emptyAllowedActions[uid] = []string{} - } - allowedActionsByUid[entityKindPanel] = emptyAllowedActions - } - - var prefix string - switch entKind { - case entityKindFolder: - prefix = dashboards.ScopeFoldersPrefix - case entityKindDatasource: - prefix = datasources.ScopePrefix - case entityKindDashboard: - prefix = dashboards.ScopeDashboardsPrefix - default: - continue - } - - allowedActionsByUid[entKind] = s.getAllowedActionsByUid(ctx, user, orgId, prefix, uids) - } - - dsActionsByUid, ok := allowedActionsByUid[entityKindDatasource] - if !ok { - dsActionsByUid = make(map[string][]string) - } - - out := make([][]allowedActions, 0, len(references)) - for _, ref := range references { - var actions []allowedActions - - selfActions := make([]string, 0) - if selfKindActions, ok := allowedActionsByUid[ref.entityKind]; ok { - if self, ok := selfKindActions[ref.uid]; ok && len(self) > 0 { - selfActions = self - } - } - - actions = append(actions, allowedActions{ - EntityKind: ref.entityKind, - UID: ref.uid, - Actions: selfActions, - }) - - for _, dsUid := range ref.dsUids { - dsActions := make([]string, 0) - if dsAct, ok := dsActionsByUid[dsUid]; ok { - dsActions = dsAct - } - - actions = append(actions, allowedActions{ - EntityKind: entityKindDatasource, - UID: dsUid, - Actions: dsActions, - }) - } - - out = append(out, actions) - } - - return out, nil -} - -func (s *StandardSearchService) getAllowedActionsByUid(ctx context.Context, user *user.SignedInUser, - orgID int64, prefix string, resourceIDs []string) map[string][]string { - if user.Permissions == nil { - return map[string][]string{} - } - - permissions, ok := user.Permissions[orgID] - if !ok { - return map[string][]string{} - } - - uidsAsMap := make(map[string]bool) - for _, uid := range resourceIDs { - uidsAsMap[uid] = true - } - - out := make(map[string][]string) - resp := accesscontrol.GetResourcesMetadata(ctx, permissions, prefix, uidsAsMap) - for uid, meta := range resp { - var actions []string - for action := range meta { - actions = append(actions, action) - } - sort.Strings(actions) - out[uid] = actions - } - return out -} - -type entityReferences struct { - entityKind entityKind - uid string - dsUids []string -} - -func getEntityReferences(resp *backend.DataResponse) ([]entityReferences, error) { - if resp == nil { - return nil, errors.New("nil response") - } - - if resp.Error != nil { - return nil, resp.Error - } - - if len(resp.Frames) == 0 { - return nil, errors.New("empty response") - } - - frame := resp.Frames[0] - - kindField, idx := frame.FieldByName("kind") - if idx == -1 { - return nil, errors.New("no kind field") - } - - dsUidField, idx := frame.FieldByName("ds_uid") - if idx == -1 { - return nil, errors.New("no ds_uid field") - } - uidField, idx := frame.FieldByName("uid") - if idx == -1 { - return nil, errors.New("no dash_uid field") - } - - if dsUidField.Len() != uidField.Len() { - return nil, errors.New("mismatched lengths") - } - - var out []entityReferences - for i := 0; i < dsUidField.Len(); i++ { - kind, ok := kindField.At(i).(string) - if !ok || kind == "" { - return nil, errors.New("invalid value in kind field") - } - - uid, ok := uidField.At(i).(string) - if !ok || uid == "" { - return nil, errors.New("invalid value in uid field") - } - - if entityKind(kind) != entityKindDashboard { - out = append(out, entityReferences{ - entityKind: entityKind(kind), - uid: uid, - }) - continue - } - - uidField, ok := uidField.At(i).(string) - if !ok || uidField == "" { - return nil, errors.New("invalid value in dash_uid field") - } - - rawDsUids, ok := dsUidField.At(i).(json.RawMessage) - if !ok { - return nil, fmt.Errorf("invalid value for uid %s in ds_uid field: %s", uidField, dsUidField.At(i)) - } - - var uids []string - if rawDsUids != nil { - jsonValue, err := rawDsUids.MarshalJSON() - if err != nil { - return nil, err - } - - err = json.Unmarshal(jsonValue, &uids) - if err != nil { - return nil, err - } - } - - out = append(out, entityReferences{entityKind: entityKindDashboard, uid: uid, dsUids: uids}) - } - - return out, nil -} diff --git a/pkg/services/searchV2/allowed_actions_test.go b/pkg/services/searchV2/allowed_actions_test.go deleted file mode 100644 index 933fd6fcefe..00000000000 --- a/pkg/services/searchV2/allowed_actions_test.go +++ /dev/null @@ -1,125 +0,0 @@ -package searchV2 - -import ( - "context" - _ "embed" - "fmt" - "testing" - - "github.com/grafana/grafana-plugin-sdk-go/backend" - "github.com/grafana/grafana-plugin-sdk-go/data" - "github.com/grafana/grafana-plugin-sdk-go/experimental" - "github.com/stretchr/testify/require" - - "github.com/grafana/grafana/pkg/infra/tracing" - ac "github.com/grafana/grafana/pkg/services/accesscontrol" - accesscontrolmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock" - "github.com/grafana/grafana/pkg/services/dashboards" - "github.com/grafana/grafana/pkg/services/datasources" - "github.com/grafana/grafana/pkg/services/featuremgmt" - "github.com/grafana/grafana/pkg/services/user" - "github.com/grafana/grafana/pkg/setting" -) - -var ( - //go:embed testdata/search_response_frame.json - exampleListFrameJSON string - - orgId = int64(1) - permissionsWithScopeAll = map[string][]string{ - datasources.ActionIDRead: {datasources.ScopeAll}, - datasources.ActionDelete: {datasources.ScopeAll}, - ac.ActionDatasourcesExplore: {datasources.ScopeAll}, - datasources.ActionQuery: {datasources.ScopeAll}, - datasources.ActionRead: {datasources.ScopeAll}, - datasources.ActionWrite: {datasources.ScopeAll}, - datasources.ActionPermissionsRead: {datasources.ScopeAll}, - datasources.ActionPermissionsWrite: {datasources.ScopeAll}, - - dashboards.ActionFoldersCreate: {dashboards.ScopeFoldersAll}, - dashboards.ActionFoldersRead: {dashboards.ScopeFoldersAll}, - dashboards.ActionFoldersWrite: {dashboards.ScopeFoldersAll}, - dashboards.ActionFoldersDelete: {dashboards.ScopeFoldersAll}, - dashboards.ActionFoldersPermissionsRead: {dashboards.ScopeFoldersAll}, - dashboards.ActionFoldersPermissionsWrite: {dashboards.ScopeFoldersAll}, - - dashboards.ActionDashboardsCreate: {dashboards.ScopeDashboardsAll}, - dashboards.ActionDashboardsRead: {dashboards.ScopeDashboardsAll}, - dashboards.ActionDashboardsWrite: {dashboards.ScopeDashboardsAll}, - dashboards.ActionDashboardsDelete: {dashboards.ScopeDashboardsAll}, - dashboards.ActionDashboardsPermissionsRead: {dashboards.ScopeDashboardsAll}, - dashboards.ActionDashboardsPermissionsWrite: {dashboards.ScopeDashboardsAll}, - } - permissionsWithUidScopes = map[string][]string{ - datasources.ActionIDRead: {}, - datasources.ActionDelete: {}, - ac.ActionDatasourcesExplore: {}, - datasources.ActionQuery: {}, - datasources.ActionRead: { - datasources.ScopeProvider.GetResourceScopeUID("datasource-2"), - datasources.ScopeProvider.GetResourceScopeUID("datasource-3"), - }, - datasources.ActionWrite: {}, - datasources.ActionPermissionsRead: {}, - datasources.ActionPermissionsWrite: {}, - - dashboards.ActionFoldersCreate: {}, - dashboards.ActionFoldersRead: { - dashboards.ScopeFoldersProvider.GetResourceScopeUID("ujaM1h6nz"), - }, - dashboards.ActionFoldersWrite: {}, - dashboards.ActionFoldersDelete: {}, - dashboards.ActionFoldersPermissionsRead: {}, - dashboards.ActionFoldersPermissionsWrite: {}, - - dashboards.ActionDashboardsCreate: {}, - dashboards.ActionDashboardsRead: {}, - dashboards.ActionDashboardsWrite: { - dashboards.ScopeDashboardsProvider.GetResourceScopeUID("7MeksYbmk"), - }, - dashboards.ActionDashboardsDelete: {}, - dashboards.ActionDashboardsPermissionsRead: {}, - dashboards.ActionDashboardsPermissionsWrite: {}, - } -) - -func service(t *testing.T) *StandardSearchService { - service, ok := ProvideService(&setting.Cfg{Search: setting.SearchSettings{}}, - nil, nil, accesscontrolmock.New(), tracing.InitializeTracerForTest(), featuremgmt.WithFeatures(), - nil, nil, nil).(*StandardSearchService) - require.True(t, ok) - return service -} - -func TestAllowedActionsForPermissionsWithScopeAll(t *testing.T) { - tests := []struct { - name string - permissions map[string][]string - }{ - { - name: "scope_all", - permissions: permissionsWithScopeAll, - }, - { - name: "scope_uids", - permissions: permissionsWithUidScopes, - }, - } - - for _, tt := range tests { - frame := &data.Frame{} - err := frame.UnmarshalJSON([]byte(exampleListFrameJSON)) - require.NoError(t, err) - - err = service(t).addAllowedActionsField(context.Background(), orgId, &user.SignedInUser{ - Permissions: map[int64]map[string][]string{ - orgId: tt.permissions, - }, - }, &backend.DataResponse{ - Frames: []*data.Frame{frame}, - }) - require.NoError(t, err) - - experimental.CheckGoldenJSONFrame(t, "testdata", fmt.Sprintf("allowed_actions_%s.golden", tt.name), frame, true) - } -} diff --git a/pkg/services/searchV2/auth.go b/pkg/services/searchV2/auth.go deleted file mode 100644 index 23c842f370a..00000000000 --- a/pkg/services/searchV2/auth.go +++ /dev/null @@ -1,58 +0,0 @@ -package searchV2 - -import ( - "context" - - "github.com/grafana/grafana/pkg/infra/db" - "github.com/grafana/grafana/pkg/infra/log" - "github.com/grafana/grafana/pkg/services/accesscontrol" - "github.com/grafana/grafana/pkg/services/dashboards" - "github.com/grafana/grafana/pkg/services/folder" - "github.com/grafana/grafana/pkg/services/user" -) - -// ResourceFilter checks if a given a uid (resource identifier) check if we have the requested permission -type ResourceFilter func(kind entityKind, uid, parentUID string) bool - -// FutureAuthService eventually implemented by the security service -type FutureAuthService interface { - GetDashboardReadFilter(ctx context.Context, orgID int64, user *user.SignedInUser) (ResourceFilter, error) -} - -var _ FutureAuthService = (*simpleAuthService)(nil) - -type simpleAuthService struct { - sql db.DB - ac accesscontrol.Service - folderService folder.Service - logger log.Logger -} - -func (a *simpleAuthService) GetDashboardReadFilter(ctx context.Context, orgID int64, user *user.SignedInUser) (ResourceFilter, error) { - canReadDashboard, canReadFolder := accesscontrol.Checker(user, dashboards.ActionDashboardsRead), accesscontrol.Checker(user, dashboards.ActionFoldersRead) - return func(kind entityKind, uid, parent string) bool { - switch kind { - case entityKindFolder: - scopes, err := dashboards.GetInheritedScopes(ctx, orgID, uid, a.folderService) - if err != nil { - a.logger.Debug("Could not retrieve inherited folder scopes:", "err", err) - } - scopes = append(scopes, dashboards.ScopeFoldersProvider.GetResourceScopeUID(uid)) - return canReadFolder(scopes...) - case entityKindDashboard: - scopes, err := dashboards.GetInheritedScopes(ctx, orgID, parent, a.folderService) - if err != nil { - a.logger.Debug("Could not retrieve inherited folder scopes:", "err", err) - } - scopes = append(scopes, dashboards.ScopeDashboardsProvider.GetResourceScopeUID(uid)) - scopes = append(scopes, dashboards.ScopeFoldersProvider.GetResourceScopeUID(parent)) - return canReadDashboard(scopes...) - - case entityKindPanel, entityKindDatasource, entityKindQuery: - // Not a dashboard or folder. Assume no access. - fallthrough - default: - return false - } - }, nil -} diff --git a/pkg/services/searchV2/bluge.go b/pkg/services/searchV2/bluge.go deleted file mode 100644 index bc670677fb6..00000000000 --- a/pkg/services/searchV2/bluge.go +++ /dev/null @@ -1,767 +0,0 @@ -package searchV2 - -import ( - "context" - "encoding/json" - "fmt" - "strconv" - "strings" - "time" - - "github.com/blugelabs/bluge" - "github.com/blugelabs/bluge/search" - "github.com/blugelabs/bluge/search/aggregations" - "github.com/grafana/grafana-plugin-sdk-go/backend" - "github.com/grafana/grafana-plugin-sdk-go/data" - - "github.com/grafana/grafana/pkg/infra/log" - "github.com/grafana/grafana/pkg/infra/slugify" - "github.com/grafana/grafana/pkg/services/folder" - "github.com/grafana/grafana/pkg/services/store/entity" -) - -const ( - documentFieldUID = "_id" // actually UID!! but bluge likes "_id" - documentFieldKind = "kind" - documentFieldTag = "tag" - documentFieldURL = "url" - documentFieldName = "name" - documentFieldName_sort = "name_sort" - documentFieldName_ngram = "name_ngram" - documentFieldLocation = "location" // parent path - documentFieldPanelType = "panel_type" - documentFieldTransformer = "transformer" - documentFieldDSUID = "ds_uid" - documentFieldDSType = "ds_type" - DocumentFieldCreatedAt = "created_at" - DocumentFieldUpdatedAt = "updated_at" -) - -func initOrgIndex(dashboards []dashboard, logger log.Logger, extendDoc ExtendDashboardFunc) (*orgIndex, error) { - dashboardWriter, err := bluge.OpenWriter(bluge.InMemoryOnlyConfig()) - if err != nil { - return nil, fmt.Errorf("error opening writer: %v", err) - } - // Not closing Writer here since we use it later while processing dashboard change events. - - start := time.Now() - label := start - - batch := bluge.NewBatch() - - // In order to reduce memory usage while initial indexing we are limiting - // the size of batch here. - docsInBatch := 0 - maxBatchSize := 100 - - flushIfRequired := func(force bool) error { - docsInBatch++ - needFlush := force || (maxBatchSize > 0 && docsInBatch >= maxBatchSize) - if !needFlush { - return nil - } - err := dashboardWriter.Batch(batch) - if err != nil { - return err - } - docsInBatch = 0 - batch.Reset() - return nil - } - - // First index the folders to construct folderIdLookup. - folderIdLookup := make(map[int64]string, 50) - folderIdLookup[0] = folder.GeneralFolderUID - for _, dash := range dashboards { - if !dash.isFolder { - continue - } - doc := getFolderDashboardDoc(dash) - if err := extendDoc(dash.uid, doc); err != nil { - return nil, err - } - batch.Insert(doc) - if err := flushIfRequired(false); err != nil { - return nil, err - } - uid := dash.uid - folderIdLookup[dash.id] = uid - } - - // Then each dashboard. - for _, dash := range dashboards { - if dash.isFolder { - continue - } - folderUID := folderIdLookup[dash.folderID] - location := folderUID - - doc := getNonFolderDashboardDoc(dash, location) - if err := extendDoc(dash.uid, doc); err != nil { - return nil, err - } - batch.Insert(doc) - if err := flushIfRequired(false); err != nil { - return nil, err - } - - // Index each panel in dashboard. - if location != "" { - location += "/" - } - location += dash.uid - docs := getDashboardPanelDocs(dash, location) - - for _, panelDoc := range docs { - batch.Insert(panelDoc) - if err := flushIfRequired(false); err != nil { - return nil, err - } - } - } - - // Flush docs in batch with force as we are in the end. - if err := flushIfRequired(true); err != nil { - return nil, err - } - - logger.Info("Finish inserting docs into index", "elapsed", time.Since(label)) - logger.Info("Finish building index", "totalElapsed", time.Since(start)) - return &orgIndex{ - writers: map[indexType]*bluge.Writer{ - indexTypeDashboard: dashboardWriter, - }, - }, err -} - -func getFolderDashboardDoc(dash dashboard) *bluge.Document { - uid := dash.uid - url := fmt.Sprintf("/dashboards/f/%s/%s", dash.uid, dash.slug) - if uid == "" { - uid = "general" - url = "/dashboards" - dash.summary.Name = "General" - dash.summary.Description = "" - } - - return newSearchDocument(uid, dash.summary.Name, dash.summary.Description, url). - AddField(bluge.NewKeywordField(documentFieldKind, string(entityKindFolder)).Aggregatable().StoreValue()). - AddField(bluge.NewDateTimeField(DocumentFieldCreatedAt, dash.created).Sortable().StoreValue()). - AddField(bluge.NewDateTimeField(DocumentFieldUpdatedAt, dash.updated).Sortable().StoreValue()) -} - -func getNonFolderDashboardDoc(dash dashboard, location string) *bluge.Document { - url := fmt.Sprintf("/d/%s/%s", dash.uid, dash.slug) - - // Dashboard document - doc := newSearchDocument(dash.uid, dash.summary.Name, dash.summary.Description, url). - AddField(bluge.NewKeywordField(documentFieldKind, string(entityKindDashboard)).Aggregatable().StoreValue()). - AddField(bluge.NewKeywordField(documentFieldLocation, location).Aggregatable().StoreValue()). - AddField(bluge.NewDateTimeField(DocumentFieldCreatedAt, dash.created).Sortable().StoreValue()). - AddField(bluge.NewDateTimeField(DocumentFieldUpdatedAt, dash.updated).Sortable().StoreValue()) - - // dashboards only use the key part of labels - for k := range dash.summary.Labels { - doc.AddField(bluge.NewKeywordField(documentFieldTag, k). - StoreValue(). - Aggregatable(). - SearchTermPositions()) - } - - for _, ref := range dash.summary.References { - if ref.Family == entity.StandardKindDataSource { - if ref.Type != "" { - doc.AddField(bluge.NewKeywordField(documentFieldDSType, ref.Type). - StoreValue(). - Aggregatable(). - SearchTermPositions()) - } - if ref.Identifier != "" { - doc.AddField(bluge.NewKeywordField(documentFieldDSUID, ref.Identifier). - StoreValue(). - Aggregatable(). - SearchTermPositions()) - } - } - } - - return doc -} - -func getDashboardPanelDocs(dash dashboard, location string) []*bluge.Document { - dashURL := fmt.Sprintf("/d/%s/%s", dash.uid, slugify.Slugify(dash.summary.Name)) - - // pre-allocating a little bit more than necessary, possibly - docs := make([]*bluge.Document, 0, len(dash.summary.Nested)) - - for _, panel := range dash.summary.Nested { - if panel.Fields["type"] == "row" { - continue // skip rows - } - idx := strings.LastIndex(panel.UID, "#") - panelId, err := strconv.Atoi(panel.UID[idx+1:]) - if err != nil { - continue - } - - url := fmt.Sprintf("%s?viewPanel=%d", dashURL, panelId) - doc := newSearchDocument(panel.UID, panel.Name, panel.Description, url). - AddField(bluge.NewKeywordField(documentFieldLocation, location).Aggregatable().StoreValue()). - AddField(bluge.NewKeywordField(documentFieldKind, string(entityKindPanel)).Aggregatable().StoreValue()) // likely want independent index for this - - for _, ref := range panel.References { - switch ref.Family { - case entity.StandardKindDashboard: - if ref.Type != "" { - doc.AddField(bluge.NewKeywordField(documentFieldDSType, ref.Type). - StoreValue(). - Aggregatable(). - SearchTermPositions()) - } - if ref.Identifier != "" { - doc.AddField(bluge.NewKeywordField(documentFieldDSUID, ref.Identifier). - StoreValue(). - Aggregatable(). - SearchTermPositions()) - } - case entity.ExternalEntityReferencePlugin: - if ref.Type == entity.StandardKindPanel && ref.Identifier != "" { - doc.AddField(bluge.NewKeywordField(documentFieldPanelType, ref.Identifier).Aggregatable().StoreValue()) - } - case entity.ExternalEntityReferenceRuntime: - if ref.Type == entity.ExternalEntityReferenceRuntime_Transformer && ref.Identifier != "" { - doc.AddField(bluge.NewKeywordField(documentFieldTransformer, ref.Identifier).Aggregatable()) - } - } - } - - docs = append(docs, doc) - } - return docs -} - -// Names need to be indexed a few ways to support key features -func newSearchDocument(uid, name, descr, url string) *bluge.Document { - doc := bluge.NewDocument(uid) - - if name != "" { - doc.AddField(bluge.NewTextField(documentFieldName, name).StoreValue().SearchTermPositions()) - doc.AddField(bluge.NewTextField(documentFieldName_ngram, name).WithAnalyzer(ngramIndexAnalyzer)) - - // Don't add a field for empty names - sortStr := formatForNameSortField(name) - if len(sortStr) > 0 { - doc.AddField(bluge.NewKeywordField(documentFieldName_sort, sortStr).Sortable()) - } - } - if url != "" { - doc.AddField(bluge.NewKeywordField(documentFieldURL, url).StoreValue()) - } - return doc -} - -func getDashboardPanelIDs(index *orgIndex, panelLocation string) ([]string, error) { - var panelIDs []string - - reader, cancel, err := index.readerForIndex(indexTypeDashboard) - if err != nil { - return nil, err - } - defer cancel() - - fullQuery := bluge.NewBooleanQuery() - fullQuery.AddMust(bluge.NewTermQuery(panelLocation).SetField(documentFieldLocation)) - fullQuery.AddMust(bluge.NewTermQuery(string(entityKindPanel)).SetField(documentFieldKind)) - req := bluge.NewAllMatches(fullQuery) - documentMatchIterator, err := reader.Search(context.Background(), req) - if err != nil { - return nil, err - } - match, err := documentMatchIterator.Next() - for err == nil && match != nil { - // load the identifier for this match - err = match.VisitStoredFields(func(field string, value []byte) bool { - if field == documentFieldUID { - panelIDs = append(panelIDs, string(value)) - } - return true - }) - if err != nil { - return nil, err - } - // load the next document match - match, err = documentMatchIterator.Next() - } - return panelIDs, err -} - -func getDocsIDsByLocationPrefix(index *orgIndex, prefix string) ([]string, error) { - var ids []string - - reader, cancel, err := index.readerForIndex(indexTypeDashboard) - if err != nil { - return nil, fmt.Errorf("error getting reader: %w", err) - } - defer cancel() - - fullQuery := bluge.NewBooleanQuery() - fullQuery.AddMust(bluge.NewPrefixQuery(prefix).SetField(documentFieldLocation)) - req := bluge.NewAllMatches(fullQuery) - documentMatchIterator, err := reader.Search(context.Background(), req) - if err != nil { - return nil, fmt.Errorf("error search: %w", err) - } - match, err := documentMatchIterator.Next() - for err == nil && match != nil { - // load the identifier for this match - err = match.VisitStoredFields(func(field string, value []byte) bool { - if field == documentFieldUID { - ids = append(ids, string(value)) - } - return true - }) - if err != nil { - return nil, err - } - // load the next document match - match, err = documentMatchIterator.Next() - } - return ids, err -} - -func getDashboardLocation(index *orgIndex, dashboardUID string) (string, bool, error) { - var dashboardLocation string - var found bool - - reader, cancel, err := index.readerForIndex(indexTypeDashboard) - if err != nil { - return "", false, err - } - defer cancel() - - fullQuery := bluge.NewBooleanQuery() - fullQuery.AddMust(bluge.NewTermQuery(dashboardUID).SetField(documentFieldUID)) - fullQuery.AddMust(bluge.NewTermQuery(string(entityKindDashboard)).SetField(documentFieldKind)) - req := bluge.NewAllMatches(fullQuery) - documentMatchIterator, err := reader.Search(context.Background(), req) - if err != nil { - return "", false, err - } - match, err := documentMatchIterator.Next() - for err == nil && match != nil { - // load the identifier for this match - err = match.VisitStoredFields(func(field string, value []byte) bool { - if field == documentFieldLocation { - dashboardLocation = string(value) - found = true - return false - } - return true - }) - if err != nil { - return "", false, err - } - // load the next document match - match, err = documentMatchIterator.Next() - } - return dashboardLocation, found, err -} - -//nolint:gocyclo -func doSearchQuery( - ctx context.Context, - logger log.Logger, - index *orgIndex, - filter ResourceFilter, - q DashboardQuery, - extender QueryExtender, - appSubUrl string, -) *backend.DataResponse { - response := &backend.DataResponse{} - header := &customMeta{} - - reader, cancel, err := index.readerForIndex(indexTypeDashboard) - if err != nil { - logger.Error("Error getting reader for dashboard index: %v", err) - response.Error = err - return response - } - defer cancel() - - hasConstraints := false - fullQuery := bluge.NewBooleanQuery() - fullQuery.AddMust(newPermissionFilter(filter, logger)) - - // Only show dashboard / folders / panels. - if len(q.Kind) > 0 { - bq := bluge.NewBooleanQuery() - for _, k := range q.Kind { - bq.AddShould(bluge.NewTermQuery(k).SetField(documentFieldKind)) - } - fullQuery.AddMust(bq) - hasConstraints = true - } - - // Explicit UID lookup (stars etc) - if len(q.UIDs) > 0 { - count := len(q.UIDs) + 3 - bq := bluge.NewBooleanQuery() - for i, v := range q.UIDs { - bq.AddShould(bluge.NewTermQuery(v). - SetField(documentFieldUID). - SetBoost(float64(count - i))) - } - fullQuery.AddMust(bq) - hasConstraints = true - } - - // Tags - if len(q.Tags) > 0 { - bq := bluge.NewBooleanQuery() - for _, v := range q.Tags { - bq.AddMust(bluge.NewTermQuery(v).SetField(documentFieldTag)) - } - fullQuery.AddMust(bq) - hasConstraints = true - } - - // Panel type - if q.PanelType != "" { - fullQuery.AddMust(bluge.NewTermQuery(q.PanelType).SetField(documentFieldPanelType)) - hasConstraints = true - } - - // Datasource - if q.Datasource != "" { - fullQuery.AddMust(bluge.NewTermQuery(q.Datasource).SetField(documentFieldDSUID)) - hasConstraints = true - } - - // DatasourceType - if q.DatasourceType != "" { - fullQuery.AddMust(bluge.NewTermQuery(q.DatasourceType).SetField(documentFieldDSType)) - hasConstraints = true - } - - // Folder - if q.Location != "" { - fullQuery.AddMust(bluge.NewTermQuery(q.Location).SetField(documentFieldLocation)) - hasConstraints = true - } - - isMatchAllQuery := q.Query == "*" || q.Query == "" - if isMatchAllQuery { - if !hasConstraints { - fullQuery.AddShould(bluge.NewMatchAllQuery()) - } - } else { - bq := bluge.NewBooleanQuery() - - bq.AddShould(NewSubstringQuery(formatForNameSortField(q.Query)). - SetField(documentFieldName_sort). - SetBoost(6)) - - if shouldUseNgram(q) { - bq.AddShould(bluge.NewMatchQuery(q.Query). - SetField(documentFieldName_ngram). - SetOperator(bluge.MatchQueryOperatorAnd). // all terms must match - SetAnalyzer(ngramQueryAnalyzer).SetBoost(1)) - } - - fullQuery.AddMust(bq) - } - - limit := 50 // default view - if q.Limit > 0 { - limit = q.Limit - } - - req := bluge.NewTopNSearch(limit, fullQuery) - if q.From > 0 { - req.SetFrom(q.From) - } - if q.Explain { - req.ExplainScores() - } - req.WithStandardAggregations() - - if q.Sort != "" { - req.SortBy([]string{q.Sort}) - header.SortBy = strings.TrimPrefix(q.Sort, "-") - } - - for _, t := range q.Facet { - lim := t.Limit - if lim < 1 { - lim = 50 - } - req.AddAggregation(t.Field, aggregations.NewTermsAggregation(search.Field(t.Field), lim)) - } - - // execute this search on the reader - documentMatchIterator, err := reader.Search(ctx, req) - if err != nil { - logger.Error("Error executing search", "err", err) - response.Error = err - return response - } - - fScore := data.NewFieldFromFieldType(data.FieldTypeFloat64, 0) - fUID := data.NewFieldFromFieldType(data.FieldTypeString, 0) - fKind := data.NewFieldFromFieldType(data.FieldTypeString, 0) - fPType := data.NewFieldFromFieldType(data.FieldTypeString, 0) - fName := data.NewFieldFromFieldType(data.FieldTypeString, 0) - fURL := data.NewFieldFromFieldType(data.FieldTypeString, 0) - fLocation := data.NewFieldFromFieldType(data.FieldTypeString, 0) - fTags := data.NewFieldFromFieldType(data.FieldTypeNullableJSON, 0) //nolint:staticcheck - fDSUIDs := data.NewFieldFromFieldType(data.FieldTypeJSON, 0) - fExplain := data.NewFieldFromFieldType(data.FieldTypeNullableJSON, 0) //nolint:staticcheck - - fScore.Name = "score" - fUID.Name = "uid" - fKind.Name = "kind" - fName.Name = "name" - fLocation.Name = "location" - fURL.Name = "url" - fURL.Config = &data.FieldConfig{ - Links: []data.DataLink{ - {Title: "link", URL: "${__value.text}"}, - }, - } - fPType.Name = "panel_type" - fDSUIDs.Name = "ds_uid" - fTags.Name = "tags" - fExplain.Name = "explain" - - frame := data.NewFrame("Query results", fKind, fUID, fName, fPType, fURL, fTags, fDSUIDs, fLocation) - if q.Explain { - frame.Fields = append(frame.Fields, fScore, fExplain) - } - frame.SetMeta(&data.FrameMeta{ - Type: "search-results", - Custom: header, - }) - - fieldLen := 0 - ext := extender.GetFramer(frame) - - locationItems := make(map[string]bool, 50) - - // iterate through the document matches - match, err := documentMatchIterator.Next() - for err == nil && match != nil { - uid := "" - kind := "" - ptype := "" - name := "" - url := "" - loc := "" - var dsUIDs []string - var tags []string - - err = match.VisitStoredFields(func(field string, value []byte) bool { - switch field { - case documentFieldUID: - uid = string(value) - case documentFieldKind: - kind = string(value) - case documentFieldPanelType: - ptype = string(value) - case documentFieldName: - name = string(value) - case documentFieldURL: - url = appSubUrl + string(value) - case documentFieldLocation: - loc = string(value) - case documentFieldDSUID: - dsUIDs = append(dsUIDs, string(value)) - case documentFieldTag: - tags = append(tags, string(value)) - default: - ext(field, value) - } - return true - }) - if err != nil { - logger.Error("Error loading stored fields", "err", err) - response.Error = err - return response - } - - fKind.Append(kind) - fUID.Append(uid) - fPType.Append(ptype) - fName.Append(name) - fURL.Append(url) - fLocation.Append(loc) - - // set a key for all path parts we return - if !q.SkipLocation { - for _, v := range strings.Split(loc, "/") { - locationItems[v] = true - } - } - - if len(tags) > 0 { - js, _ := json.Marshal(tags) - jsb := json.RawMessage(js) - fTags.Append(&jsb) - } else { - fTags.Append(nil) - } - - if len(dsUIDs) == 0 { - dsUIDs = []string{} - } - - js, _ := json.Marshal(dsUIDs) - jsb := json.RawMessage(js) - fDSUIDs.Append(jsb) - - if q.Explain { - if isMatchAllQuery { - fScore.Append(float64(fieldLen + q.From)) - } else { - fScore.Append(match.Score) - } - if match.Explanation != nil { - js, _ := json.Marshal(&match.Explanation) - jsb := json.RawMessage(js) - fExplain.Append(&jsb) - } else { - fExplain.Append(nil) - } - } - - // extend fields to match the longest field - fieldLen++ - for _, f := range frame.Fields { - if fieldLen > f.Len() { - f.Extend(fieldLen - f.Len()) - } - } - - // load the next document match - match, err = documentMatchIterator.Next() - } - - // Must call after iterating :) - aggs := documentMatchIterator.Aggregations() - - header.Count = aggs.Count() // Total count - if q.Explain { - header.MaxScore = aggs.Metric("max_score") - } - - if len(locationItems) > 0 && !q.SkipLocation { - header.Locations = getLocationLookupInfo(ctx, reader, locationItems) - } - - response.Frames = append(response.Frames, frame) - - for _, t := range q.Facet { - bbb := aggs.Buckets(t.Field) - if bbb != nil { - size := len(bbb) - - fName := data.NewFieldFromFieldType(data.FieldTypeString, size) - fName.Name = t.Field - - fCount := data.NewFieldFromFieldType(data.FieldTypeUint64, size) - fCount.Name = "Count" - - for i, v := range bbb { - fName.Set(i, v.Name()) - fCount.Set(i, v.Count()) - } - - response.Frames = append(response.Frames, data.NewFrame("Facet: "+t.Field, fName, fCount)) - } - } - - return response -} - -func shouldUseNgram(q DashboardQuery) bool { - var tokens []string - if len(q.Query) > ngramEdgeFilterMaxLength { - tokens = strings.Fields(q.Query) - for _, k := range tokens { - // ngram will never match if at least one input token exceeds the max token length, - // as all tokens must match simultaneously with the `bluge.MatchQueryOperatorAnd` operator - if len(k) > ngramEdgeFilterMaxLength { - return false - } - } - } - return true -} - -func formatForNameSortField(name string) string { - return strings.Trim(strings.ToUpper(name), " ") -} - -func getLocationLookupInfo(ctx context.Context, reader *bluge.Reader, uids map[string]bool) map[string]locationItem { - res := make(map[string]locationItem, len(uids)) - bq := bluge.NewBooleanQuery() - for k := range uids { - bq.AddShould(bluge.NewTermQuery(k).SetField(documentFieldUID)) - } - - req := bluge.NewAllMatches(bq) - - documentMatchIterator, err := reader.Search(ctx, req) - if err != nil { - return res - } - - dvfieldNames := []string{"type"} - sctx := search.NewSearchContext(0, 0) - - // execute this search on the reader - // iterate through the document matches - match, err := documentMatchIterator.Next() - for err == nil && match != nil { - err = match.LoadDocumentValues(sctx, dvfieldNames) - if err != nil { - continue - } - - uid := "" - item := locationItem{} - - _ = match.VisitStoredFields(func(field string, value []byte) bool { - switch field { - case documentFieldUID: - uid = string(value) - case documentFieldKind: - item.Kind = string(value) - case documentFieldName: - item.Name = string(value) - case documentFieldURL: - item.URL = string(value) - } - return true - }) - - res[uid] = item - - // load the next document match - match, err = documentMatchIterator.Next() - } - - return res -} - -type locationItem struct { - Name string `json:"name"` - Kind string `json:"kind"` - URL string `json:"url"` -} - -type customMeta struct { - Count uint64 `json:"count"` - MaxScore float64 `json:"max_score,omitempty"` - Locations map[string]locationItem `json:"locationInfo,omitempty"` - SortBy string `json:"sortBy,omitempty"` -} diff --git a/pkg/services/searchV2/extender.go b/pkg/services/searchV2/extender.go deleted file mode 100644 index c2cb16f27aa..00000000000 --- a/pkg/services/searchV2/extender.go +++ /dev/null @@ -1,48 +0,0 @@ -package searchV2 - -import ( - "github.com/blugelabs/bluge" - "github.com/grafana/grafana-plugin-sdk-go/data" -) - -type ExtendDashboardFunc func(uid string, doc *bluge.Document) error -type FramerFunc func(field string, value []byte) - -type QueryExtender interface { - GetFramer(frame *data.Frame) FramerFunc -} - -type DocumentExtender interface { - GetDashboardExtender(orgID int64, uids ...string) ExtendDashboardFunc -} - -type DashboardIndexExtender interface { - GetDocumentExtender() DocumentExtender - GetQueryExtender(query DashboardQuery) QueryExtender -} - -type NoopExtender struct{} - -func (n NoopExtender) GetDocumentExtender() DocumentExtender { - return &NoopDocumentExtender{} -} - -func (n NoopExtender) GetQueryExtender(query DashboardQuery) QueryExtender { - return &NoopQueryExtender{} -} - -type NoopDocumentExtender struct{} - -func (n NoopDocumentExtender) GetDashboardExtender(_ int64, _ ...string) ExtendDashboardFunc { - return func(uid string, doc *bluge.Document) error { - return nil - } -} - -type NoopQueryExtender struct{} - -func (n NoopQueryExtender) GetFramer(_ *data.Frame) FramerFunc { - return func(field string, value []byte) { - // really noop - } -} diff --git a/pkg/services/searchV2/filter.go b/pkg/services/searchV2/filter.go deleted file mode 100644 index d899ddf59b4..00000000000 --- a/pkg/services/searchV2/filter.go +++ /dev/null @@ -1,142 +0,0 @@ -package searchV2 - -import ( - "regexp" - "strings" - - "github.com/blugelabs/bluge" - "github.com/blugelabs/bluge/search" - "github.com/blugelabs/bluge/search/searcher" - "github.com/blugelabs/bluge/search/similarity" - - "github.com/grafana/grafana/pkg/infra/log" - "github.com/grafana/grafana/pkg/services/store/entity" -) - -type PermissionFilter struct { - log log.Logger - filter ResourceFilter -} - -type entityKind string - -const ( - entityKindPanel entityKind = entity.StandardKindPanel - entityKindDashboard entityKind = entity.StandardKindDashboard - entityKindFolder entityKind = entity.StandardKindFolder - entityKindDatasource entityKind = entity.StandardKindDataSource - entityKindQuery entityKind = entity.StandardKindQuery -) - -func (r entityKind) IsValid() bool { - return r == entityKindPanel || r == entityKindDashboard || r == entityKindFolder -} - -func (r entityKind) supportsAuthzCheck() bool { - return r == entityKindPanel || r == entityKindDashboard || r == entityKindFolder -} - -var ( - permissionFilterFields = []string{documentFieldUID, documentFieldKind, documentFieldLocation} - panelIdFieldRegex = regexp.MustCompile(`^(.*)#([0-9]{1,4})$`) - panelIdFieldDashboardUidSubmatchIndex = 1 - panelIdFieldPanelIdSubmatchIndex = 2 - panelIdFieldRegexExpectedSubmatchCount = 3 // submatches[0] - whole string - - _ bluge.Query = (*PermissionFilter)(nil) -) - -func newPermissionFilter(resourceFilter ResourceFilter, log log.Logger) *PermissionFilter { - return &PermissionFilter{ - filter: resourceFilter, - log: log, - } -} - -func (q *PermissionFilter) logAccessDecision(decision bool, kind any, id string, reason string, ctx ...any) { - if true { - return // TOO much logging right now - } - - ctx = append(ctx, "kind", kind, "id", id, "reason", reason) - if decision { - q.log.Debug("Allowing access", ctx...) - } else { - q.log.Info("Denying access", ctx...) - } -} - -func (q *PermissionFilter) canAccess(kind entityKind, id, location string) bool { - if !kind.supportsAuthzCheck() { - q.logAccessDecision(false, kind, id, "entityDoesNotSupportAuthz") - return false - } - - // TODO add `kind` to the `ResourceFilter` interface so that we can move the switch out of here - // - switch kind { - case entityKindFolder, entityKindDashboard: - decision := q.filter(kind, id, location) - q.logAccessDecision(decision, kind, id, "resourceFilter") - return decision - case entityKindPanel: - matches := panelIdFieldRegex.FindStringSubmatch(id) - submatchCount := len(matches) - if submatchCount != panelIdFieldRegexExpectedSubmatchCount { - q.logAccessDecision(false, kind, id, "invalidPanelIdFieldRegexSubmatchCount", "submatchCount", submatchCount, "expectedSubmatchCount", panelIdFieldRegexExpectedSubmatchCount) - return false - } - dashboardUid := matches[panelIdFieldDashboardUidSubmatchIndex] - - // Location is / - if !strings.HasSuffix(location, "/"+dashboardUid) { - q.logAccessDecision(false, kind, id, "invalidLocation", "location", location, "dashboardUid", dashboardUid) - return false - } - folderUid := location[:len(location)-len(dashboardUid)-1] - - decision := q.filter(entityKindDashboard, dashboardUid, folderUid) - q.logAccessDecision(decision, kind, id, "resourceFilter", "folderUid", folderUid, "dashboardUid", dashboardUid, "panelId", matches[panelIdFieldPanelIdSubmatchIndex]) - return decision - default: - q.logAccessDecision(false, kind, id, "reason", "unknownKind") - return false - } -} - -func (q *PermissionFilter) Searcher(i search.Reader, options search.SearcherOptions) (search.Searcher, error) { - dvReader, err := i.DocumentValueReader(permissionFilterFields) - if err != nil { - return nil, err - } - - s, err := searcher.NewMatchAllSearcher(i, 1, similarity.ConstantScorer(1), options) - if err != nil { - return nil, err - } - return searcher.NewFilteringSearcher(s, func(d *search.DocumentMatch) bool { - var kind, id, location string - err := dvReader.VisitDocumentValues(d.Number, func(field string, term []byte) { - switch field { - case documentFieldKind: - kind = string(term) - case documentFieldUID: - id = string(term) - case documentFieldLocation: - location = string(term) - } - }) - if err != nil { - q.logAccessDecision(false, kind, id, "errorWhenVisitingDocumentValues") - return false - } - - e := entityKind(kind) - if !e.IsValid() { - q.logAccessDecision(false, kind, id, "invalidEntityKind") - return false - } - - return q.canAccess(e, id, location) - }), err -} diff --git a/pkg/services/searchV2/http.go b/pkg/services/searchV2/http.go deleted file mode 100644 index 547cada787e..00000000000 --- a/pkg/services/searchV2/http.go +++ /dev/null @@ -1,80 +0,0 @@ -package searchV2 - -import ( - "encoding/json" - "errors" - "io" - "net/http" - - "github.com/grafana/grafana-plugin-sdk-go/backend" - "github.com/grafana/grafana-plugin-sdk-go/data" - "github.com/prometheus/client_golang/prometheus" - - "github.com/grafana/grafana/pkg/api/response" - "github.com/grafana/grafana/pkg/api/routing" - "github.com/grafana/grafana/pkg/middleware" - contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model" -) - -type SearchHTTPService interface { - RegisterHTTPRoutes(storageRoute routing.RouteRegister) -} - -type searchHTTPService struct { - search SearchService -} - -func ProvideSearchHTTPService(search SearchService) SearchHTTPService { - return &searchHTTPService{search: search} -} - -func (s *searchHTTPService) RegisterHTTPRoutes(storageRoute routing.RouteRegister) { - storageRoute.Post("/", middleware.ReqSignedIn, routing.Wrap(s.doQuery)) -} - -func (s *searchHTTPService) doQuery(c *contextmodel.ReqContext) response.Response { - ctx, span := tracer.Start(c.Req.Context(), "searchV2.doQuery") - defer span.End() - searchReadinessCheckResp := s.search.IsReady(ctx, c.GetOrgID()) - if !searchReadinessCheckResp.IsReady { - dashboardSearchNotServedRequestsCounter.With(prometheus.Labels{ - "reason": searchReadinessCheckResp.Reason, - }).Inc() - - return response.JSON(http.StatusOK, &backend.DataResponse{ - Frames: []*data.Frame{{ - Name: "Loading", - }}, - Error: nil, - }) - } - - body, err := io.ReadAll(c.Req.Body) - if err != nil { - return response.Error(http.StatusInternalServerError, "error reading bytes", err) - } - - query := &DashboardQuery{} - err = json.Unmarshal(body, query) - if err != nil { - return response.Error(http.StatusBadRequest, "error parsing body", err) - } - - resp := s.search.doDashboardQuery(ctx, c.SignedInUser, c.GetOrgID(), *query) - - if resp.Error != nil { - return response.Error(http.StatusInternalServerError, "error handling search request", resp.Error) - } - - if len(resp.Frames) == 0 { - msg := "invalid search response" - return response.Error(http.StatusInternalServerError, msg, errors.New(msg)) - } - - bytes, err := resp.MarshalJSON() - if err != nil { - return response.Error(http.StatusInternalServerError, "error marshalling response", err) - } - - return response.JSON(http.StatusOK, bytes) -} diff --git a/pkg/services/searchV2/index.go b/pkg/services/searchV2/index.go deleted file mode 100644 index 6a59e53963b..00000000000 --- a/pkg/services/searchV2/index.go +++ /dev/null @@ -1,971 +0,0 @@ -package searchV2 - -import ( - "bytes" - "context" - "errors" - "fmt" - "os" - "os/exec" - "runtime" - "strconv" - "strings" - "sync" - "time" - - "github.com/blugelabs/bluge" - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/trace" - - "github.com/grafana/grafana/pkg/infra/db" - "github.com/grafana/grafana/pkg/infra/log" - "github.com/grafana/grafana/pkg/infra/tracing" - "github.com/grafana/grafana/pkg/services/featuremgmt" - "github.com/grafana/grafana/pkg/services/folder" - "github.com/grafana/grafana/pkg/services/store" - "github.com/grafana/grafana/pkg/services/store/entity" - kdash "github.com/grafana/grafana/pkg/services/store/kind/dashboard" - "github.com/grafana/grafana/pkg/setting" -) - -type dashboardLoader interface { - // LoadDashboards returns slice of dashboards. If dashboardUID is empty – then - // implementation must return all dashboards in instance to build an entire - // dashboard index for an organization. If dashboardUID is not empty – then only - // return dashboard with specified UID or empty slice if not found (this is required - // to apply partial update). - LoadDashboards(ctx context.Context, orgID int64, dashboardUID string) ([]dashboard, error) -} - -type eventStore interface { - GetLastEvent(ctx context.Context) (*store.EntityEvent, error) - GetAllEventsAfter(ctx context.Context, id int64) ([]*store.EntityEvent, error) -} - -type dashboard struct { - id int64 - uid string - isFolder bool - folderID int64 - folderUID string - slug string - created time.Time - updated time.Time - - // Use generic structure - summary *entity.EntitySummary -} - -// buildSignal is sent when search index is accessed in organization for which -// we have not constructed an index yet. -type buildSignal struct { - orgID int64 - done chan error -} - -type orgIndex struct { - writers map[indexType]*bluge.Writer -} - -type indexType string - -const ( - indexTypeDashboard indexType = "dashboard" -) - -func (i *orgIndex) writerForIndex(idxType indexType) *bluge.Writer { - return i.writers[idxType] -} - -func (i *orgIndex) readerForIndex(idxType indexType) (*bluge.Reader, func(), error) { - reader, err := i.writers[idxType].Reader() - if err != nil { - return nil, nil, err - } - return reader, func() { _ = reader.Close() }, nil -} - -type searchIndex struct { - mu sync.RWMutex - loader dashboardLoader - perOrgIndex map[int64]*orgIndex - initializedOrgs map[int64]bool - initialIndexingComplete bool - initializationMutex sync.RWMutex - eventStore eventStore - logger log.Logger - buildSignals chan buildSignal - extender DocumentExtender - syncCh chan chan struct{} - tracer tracing.Tracer - features featuremgmt.FeatureToggles - settings setting.SearchSettings -} - -func newSearchIndex(dashLoader dashboardLoader, evStore eventStore, extender DocumentExtender, tracer tracing.Tracer, features featuremgmt.FeatureToggles, settings setting.SearchSettings) *searchIndex { - return &searchIndex{ - loader: dashLoader, - eventStore: evStore, - perOrgIndex: map[int64]*orgIndex{}, - initializedOrgs: map[int64]bool{}, - logger: log.New("searchIndex"), - buildSignals: make(chan buildSignal), - extender: extender, - syncCh: make(chan chan struct{}), - tracer: tracer, - features: features, - settings: settings, - } -} - -func (i *searchIndex) isInitialized(_ context.Context, orgId int64) IsSearchReadyResponse { - i.initializationMutex.RLock() - orgInitialized := i.initializedOrgs[orgId] - initialInitComplete := i.initialIndexingComplete - i.initializationMutex.RUnlock() - - if orgInitialized && initialInitComplete { - return IsSearchReadyResponse{IsReady: true} - } - - if !initialInitComplete { - return IsSearchReadyResponse{IsReady: false, Reason: "initial-indexing-ongoing"} - } - - i.triggerBuildingOrgIndex(orgId) - return IsSearchReadyResponse{IsReady: false, Reason: "org-indexing-ongoing"} -} - -func (i *searchIndex) triggerBuildingOrgIndex(orgId int64) { - go func() { - ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute) - defer cancel() - - doneIndexing := make(chan error, 1) - signal := buildSignal{orgID: orgId, done: doneIndexing} - select { - case i.buildSignals <- signal: - case <-ctx.Done(): - i.logger.Warn("Failed to send a build signal to initialize org index", "orgId", orgId) - return - } - select { - case err := <-doneIndexing: - if err != nil { - i.logger.Error("Failed to build org index", "orgId", orgId, "error", err) - } else { - i.logger.Debug("Successfully built org index", "orgId", orgId) - } - case <-ctx.Done(): - i.logger.Warn("Building org index timeout", "orgId", orgId) - } - }() -} - -func (i *searchIndex) sync(ctx context.Context) error { - doneCh := make(chan struct{}, 1) - select { - case i.syncCh <- doneCh: - case <-ctx.Done(): - return ctx.Err() - } - select { - case <-doneCh: - return nil - case <-ctx.Done(): - return ctx.Err() - } -} - -func (i *searchIndex) run(ctx context.Context, orgIDs []int64, reIndexSignalCh chan struct{}) error { - i.logger.Info("Initializing SearchV2", "dashboardLoadingBatchSize", i.settings.DashboardLoadingBatchSize, "fullReindexInterval", i.settings.FullReindexInterval, "indexUpdateInterval", i.settings.IndexUpdateInterval) - initialSetupCtx, initialSetupSpan := i.tracer.Start(ctx, "searchV2 initialSetup") - - reIndexInterval := i.settings.FullReindexInterval - fullReIndexTimer := time.NewTimer(reIndexInterval) - defer fullReIndexTimer.Stop() - - partialUpdateInterval := i.settings.IndexUpdateInterval - partialUpdateTimer := time.NewTimer(partialUpdateInterval) - defer partialUpdateTimer.Stop() - - var lastEventID int64 - lastEvent, err := i.eventStore.GetLastEvent(initialSetupCtx) - if err != nil { - initialSetupSpan.End() - return err - } - if lastEvent != nil { - lastEventID = lastEvent.Id - } - - err = i.buildInitialIndexes(initialSetupCtx, orgIDs) - if err != nil { - initialSetupSpan.End() - return err - } - - // This semaphore channel allows limiting concurrent async re-indexing routines to 1. - asyncReIndexSemaphore := make(chan struct{}, 1) - - // Channel to handle signals about asynchronous full re-indexing completion. - reIndexDoneCh := make(chan int64, 1) - - i.initializationMutex.Lock() - i.initialIndexingComplete = true - i.initializationMutex.Unlock() - - initialSetupSpan.End() - - for { - select { - case doneCh := <-i.syncCh: - // Executed on search read requests to make sure index is consistent. - lastEventID = i.applyIndexUpdates(ctx, lastEventID) - close(doneCh) - case <-partialUpdateTimer.C: - // Periodically apply updates collected in entity events table. - partialIndexUpdateCtx, span := i.tracer.Start(ctx, "searchV2 partial update timer") - lastEventID = i.applyIndexUpdates(partialIndexUpdateCtx, lastEventID) - span.End() - partialUpdateTimer.Reset(partialUpdateInterval) - case <-reIndexSignalCh: - // External systems may trigger re-indexing, at this moment provisioning does this. - i.logger.Info("Full re-indexing due to external signal") - fullReIndexTimer.Reset(0) - case signal := <-i.buildSignals: - buildSignalCtx, span := i.tracer.Start(ctx, "searchV2 build signal") - - // When search read request meets new not-indexed org we build index for it. - i.mu.RLock() - _, ok := i.perOrgIndex[signal.orgID] - if ok { - span.End() - // Index for org already exists, do nothing. - i.mu.RUnlock() - close(signal.done) - continue - } - i.mu.RUnlock() - lastIndexedEventID := lastEventID - // Prevent full re-indexing while we are building index for new org. - // Full re-indexing will be later re-started in `case lastIndexedEventID := <-reIndexDoneCh` - // branch. - fullReIndexTimer.Stop() - go func() { - defer span.End() - // We need semaphore here since asynchronous re-indexing may be in progress already. - asyncReIndexSemaphore <- struct{}{} - defer func() { <-asyncReIndexSemaphore }() - _, err = i.buildOrgIndex(buildSignalCtx, signal.orgID) - signal.done <- err - reIndexDoneCh <- lastIndexedEventID - }() - case <-fullReIndexTimer.C: - fullReindexCtx, span := i.tracer.Start(ctx, "searchV2 full reindex timer") - - // Periodically rebuild indexes since we could miss updates. At this moment we are issuing - // entity events non-atomically (outside of transaction) and do not cover all possible dashboard - // change places, so periodic re-indexing fixes possibly broken state. But ideally we should - // come to an approach which does not require periodic re-indexing at all. One possible way - // is to use DB triggers, see https://github.com/grafana/grafana/pull/47712. - lastIndexedEventID := lastEventID - go func() { - defer span.End() - // Do full re-index asynchronously to avoid blocking index synchronization - // on read for a long time. - - // We need semaphore here since re-indexing due to build signal may be in progress already. - asyncReIndexSemaphore <- struct{}{} - defer func() { <-asyncReIndexSemaphore }() - - started := time.Now() - i.logger.Info("Start re-indexing", i.withCtxData(fullReindexCtx)...) - i.reIndexFromScratch(fullReindexCtx) - i.logger.Info("Full re-indexing finished", i.withCtxData(fullReindexCtx, "fullReIndexElapsed", time.Since(started))...) - reIndexDoneCh <- lastIndexedEventID - }() - case lastIndexedEventID := <-reIndexDoneCh: - // Asynchronous re-indexing is finished. Set lastEventID to the value which - // was actual at the re-indexing start – so that we could re-apply all the - // events happened during async index build process and make sure it's consistent. - if lastEventID != lastIndexedEventID { - i.logger.Info("Re-apply event ID to last indexed", "currentEventID", lastEventID, "lastIndexedEventID", lastIndexedEventID) - lastEventID = lastIndexedEventID - // Apply events immediately. - partialUpdateTimer.Reset(0) - } - fullReIndexTimer.Reset(reIndexInterval) - case <-ctx.Done(): - return ctx.Err() - } - } -} - -func (i *searchIndex) buildInitialIndexes(ctx context.Context, orgIDs []int64) error { - started := time.Now() - i.logger.Info("Start building in-memory indexes") - for _, orgID := range orgIDs { - err := i.buildInitialIndex(ctx, orgID) - if err != nil { - return fmt.Errorf("can't build initial dashboard search index for org %d: %w", orgID, err) - } - } - i.logger.Info("Finish building in-memory indexes", "elapsed", time.Since(started)) - return nil -} - -func (i *searchIndex) buildInitialIndex(ctx context.Context, orgID int64) error { - debugCtx, debugCtxCancel := context.WithCancel(ctx) - if os.Getenv("GF_SEARCH_DEBUG") != "" { - go i.debugResourceUsage(debugCtx, 200*time.Millisecond) - } - - started := time.Now() - numDashboards, err := i.buildOrgIndex(ctx, orgID) - if err != nil { - debugCtxCancel() - return fmt.Errorf("can't build dashboard search index for org ID 1: %w", err) - } - i.logger.Info("Indexing for org finished", "orgIndexElapsed", time.Since(started), "orgId", orgID, "numDashboards", numDashboards) - debugCtxCancel() - - if os.Getenv("GF_SEARCH_DEBUG") != "" { - // May help to estimate size of index when introducing changes. Though it's not a direct - // match to a memory consumption, but at least make give some relative difference understanding. - // Moreover, changes in indexing can cause additional memory consumption upon initial index build - // which is not reflected here. - i.reportSizeOfIndexDiskBackup(orgID) - } - return nil -} - -// This is a naive implementation of process CPU getting (credits to -// https://stackoverflow.com/a/11357813/1288429). Should work on both Linux and Darwin. -// Since we only use this during development – seems simple and cheap solution to get -// process CPU usage in cross-platform way. -func getProcessCPU(currentPid int) (float64, error) { - cmd := exec.Command("ps", "aux") - var out bytes.Buffer - cmd.Stdout = &out - err := cmd.Run() - if err != nil { - return 0, err - } - for { - line, err := out.ReadString('\n') - if err != nil { - break - } - tokens := strings.Split(line, " ") - ft := make([]string, 0) - for _, t := range tokens { - if t != "" && t != "\t" { - ft = append(ft, t) - } - } - pid, err := strconv.Atoi(ft[1]) - if err != nil { - continue - } - if pid != currentPid { - continue - } - cpu, err := strconv.ParseFloat(ft[2], 64) - if err != nil { - return 0, err - } - return cpu, nil - } - return 0, errors.New("process not found") -} - -func (i *searchIndex) debugResourceUsage(ctx context.Context, frequency time.Duration) { - var maxHeapInuse uint64 - var maxSys uint64 - - captureMemStats := func() { - var m runtime.MemStats - runtime.ReadMemStats(&m) - if m.HeapInuse > maxHeapInuse { - maxHeapInuse = m.HeapInuse - } - if m.Sys > maxSys { - maxSys = m.Sys - } - } - - var cpuUtilization []float64 - - captureCPUStats := func() { - cpu, err := getProcessCPU(os.Getpid()) - if err != nil { - i.logger.Error("CPU stats error", "error", err) - return - } - // Just collect CPU utilization to a slice and show in the of index build. - cpuUtilization = append(cpuUtilization, cpu) - } - - captureMemStats() - captureCPUStats() - - for { - select { - case <-ctx.Done(): - i.logger.Warn("Resource usage during indexing", "maxHeapInUse", formatBytes(maxHeapInuse), "maxSys", formatBytes(maxSys), "cpuPercent", cpuUtilization) - return - case <-time.After(frequency): - captureMemStats() - captureCPUStats() - } - } -} - -func (i *searchIndex) reportSizeOfIndexDiskBackup(orgID int64) { - index, _ := i.getOrgIndex(orgID) - reader, cancel, err := index.readerForIndex(indexTypeDashboard) - if err != nil { - i.logger.Warn("Error getting reader", "error", err) - return - } - defer cancel() - - // create a temp directory to store the index - tmpDir, err := os.MkdirTemp("", "grafana.dashboard_index") - if err != nil { - i.logger.Error("Can't create temp dir", "error", err) - return - } - defer func() { - err := os.RemoveAll(tmpDir) - if err != nil { - i.logger.Error("Can't remove temp dir", "error", err, "tmpDir", tmpDir) - return - } - }() - - cancelCh := make(chan struct{}) - err = reader.Backup(tmpDir, cancelCh) - if err != nil { - i.logger.Error("Can't create index disk backup", "error", err) - return - } - - size, err := dirSize(tmpDir) - if err != nil { - i.logger.Error("Can't calculate dir size", "error", err) - return - } - - i.logger.Warn("Size of index disk backup", "size", formatBytes(uint64(size))) -} - -func (i *searchIndex) buildOrgIndex(ctx context.Context, orgID int64) (int, error) { - spanCtx, span := i.tracer.Start(ctx, "searchV2 buildOrgIndex", trace.WithAttributes( - attribute.Int64("org_id", orgID), - )) - - started := time.Now() - ctx, cancel := context.WithTimeout(spanCtx, time.Minute) - ctx = log.InitCounter(ctx) - - defer func() { - span.End() - cancel() - }() - - i.logger.Info("Start building org index", "orgId", orgID) - dashboards, err := i.loader.LoadDashboards(ctx, orgID, "") - orgSearchIndexLoadTime := time.Since(started) - - if err != nil { - return 0, fmt.Errorf("error loading dashboards: %w, elapsed: %s", err, orgSearchIndexLoadTime.String()) - } - i.logger.Info("Finish loading org dashboards", "elapsed", orgSearchIndexLoadTime, "orgId", orgID) - - dashboardExtender := i.extender.GetDashboardExtender(orgID) - - _, initOrgIndexSpan := i.tracer.Start(ctx, "searchV2 buildOrgIndex init org index", trace.WithAttributes( - attribute.Int64("org_id", orgID), - attribute.Int("dashboardCount", len(dashboards)), - )) - - index, err := initOrgIndex(dashboards, i.logger, dashboardExtender) - - initOrgIndexSpan.End() - - if err != nil { - return 0, fmt.Errorf("error initializing index: %w", err) - } - orgSearchIndexTotalTime := time.Since(started) - orgSearchIndexBuildTime := orgSearchIndexTotalTime - orgSearchIndexLoadTime - - i.logger.Info("Re-indexed dashboards for organization", - i.withCtxData(ctx, "orgId", orgID, - "orgSearchIndexLoadTime", orgSearchIndexLoadTime, - "orgSearchIndexBuildTime", orgSearchIndexBuildTime, - "orgSearchIndexTotalTime", orgSearchIndexTotalTime, - "orgSearchDashboardCount", len(dashboards))...) - - i.mu.Lock() - if oldIndex, ok := i.perOrgIndex[orgID]; ok { - for _, w := range oldIndex.writers { - _ = w.Close() - } - } - i.perOrgIndex[orgID] = index - i.mu.Unlock() - - i.initializationMutex.Lock() - i.initializedOrgs[orgID] = true - i.initializationMutex.Unlock() - - if orgID == 1 { - go func() { - if reader, cancel, err := index.readerForIndex(indexTypeDashboard); err == nil { - defer cancel() - updateUsageStats(context.Background(), reader, i.logger, i.tracer) - } - }() - } - return len(dashboards), nil -} - -func (i *searchIndex) getOrgIndex(orgID int64) (*orgIndex, bool) { - i.mu.RLock() - defer i.mu.RUnlock() - r, ok := i.perOrgIndex[orgID] - return r, ok -} - -func (i *searchIndex) getOrCreateOrgIndex(ctx context.Context, orgID int64) (*orgIndex, error) { - index, ok := i.getOrgIndex(orgID) - if !ok { - // For non-main organization indexes are built lazily. - // If we don't have an index then we are blocking here until an index for - // an organization is ready. This actually takes time only during the first - // access, all the consequent search requests do not fall into this branch. - doneIndexing := make(chan error, 1) - signal := buildSignal{orgID: orgID, done: doneIndexing} - select { - case i.buildSignals <- signal: - case <-ctx.Done(): - return nil, ctx.Err() - } - select { - case err := <-doneIndexing: - if err != nil { - return nil, err - } - case <-ctx.Done(): - return nil, ctx.Err() - } - index, _ = i.getOrgIndex(orgID) - } - return index, nil -} - -func (i *searchIndex) reIndexFromScratch(ctx context.Context) { - i.mu.RLock() - orgIDs := make([]int64, 0, len(i.perOrgIndex)) - for orgID := range i.perOrgIndex { - orgIDs = append(orgIDs, orgID) - } - i.mu.RUnlock() - - for _, orgID := range orgIDs { - _, err := i.buildOrgIndex(ctx, orgID) - if err != nil { - i.logger.Error("Error re-indexing dashboards for organization", "orgId", orgID, "error", err) - continue - } - } -} - -func (i *searchIndex) withCtxData(ctx context.Context, params ...any) []any { - traceID := tracing.TraceIDFromContext(ctx, false) - if traceID != "" { - params = append(params, "traceID", traceID) - } - - return params -} - -func (i *searchIndex) applyIndexUpdates(ctx context.Context, lastEventID int64) int64 { - ctx = log.InitCounter(ctx) - events, err := i.eventStore.GetAllEventsAfter(ctx, lastEventID) - if err != nil { - i.logger.Error("Can't load events", "error", err) - return lastEventID - } - if len(events) == 0 { - return lastEventID - } - started := time.Now() - for _, e := range events { - err := i.applyEventOnIndex(ctx, e) - if err != nil { - i.logger.Error("Can't apply event", "error", err) - return lastEventID - } - lastEventID = e.Id - } - i.logger.Info("Index updates applied", i.withCtxData(ctx, "indexEventsAppliedElapsed", time.Since(started), "numEvents", len(events))...) - return lastEventID -} - -func (i *searchIndex) applyEventOnIndex(ctx context.Context, e *store.EntityEvent) error { - i.logger.Debug("Processing event", "event", e) - - if !strings.HasPrefix(e.EntityId, "database/") { - i.logger.Warn("Unknown storage", "entityId", e.EntityId) - return nil - } - // database/org/entityType/path* - parts := strings.SplitN(strings.TrimPrefix(e.EntityId, "database/"), "/", 3) - if len(parts) != 3 { - i.logger.Error("Can't parse entityId", "entityId", e.EntityId) - return nil - } - orgIDStr := parts[0] - orgID, err := strconv.ParseInt(orgIDStr, 10, 64) - if err != nil { - i.logger.Error("Can't extract org ID", "entityId", e.EntityId) - return nil - } - kind := store.EntityType(parts[1]) - uid := parts[2] - return i.applyEvent(ctx, orgID, kind, uid, e.EventType) -} - -func (i *searchIndex) applyEvent(ctx context.Context, orgID int64, kind store.EntityType, uid string, _ store.EntityEventType) error { - i.mu.Lock() - _, ok := i.perOrgIndex[orgID] - if !ok { - // Skip event for org not yet indexed. - i.mu.Unlock() - return nil - } - i.mu.Unlock() - - // Both dashboard and folder share same DB table. - dbDashboards, err := i.loader.LoadDashboards(ctx, orgID, uid) - if err != nil { - return err - } - - i.mu.Lock() - defer i.mu.Unlock() - - index, ok := i.perOrgIndex[orgID] - if !ok { - // Skip event for org not yet fully indexed. - return nil - } - - // In the future we can rely on operation types to reduce work here. - if len(dbDashboards) == 0 { - switch kind { - case store.EntityTypeDashboard: - err = i.removeDashboard(ctx, index, uid) - case store.EntityTypeFolder: - err = i.removeFolder(ctx, index, uid) - default: - return nil - } - } else { - err = i.updateDashboard(ctx, orgID, index, dbDashboards[0]) - } - if err != nil { - return err - } - return nil -} - -func (i *searchIndex) removeDashboard(_ context.Context, index *orgIndex, dashboardUID string) error { - dashboardLocation, ok, err := getDashboardLocation(index, dashboardUID) - if err != nil { - return err - } - if !ok { - // No dashboard, nothing to remove. - return nil - } - - // Find all panel docs to remove with dashboard. - panelLocation := dashboardUID - if dashboardLocation != "" { - panelLocation = dashboardLocation + "/" + dashboardUID - } - panelIDs, err := getDocsIDsByLocationPrefix(index, panelLocation) - if err != nil { - return err - } - - writer := index.writerForIndex(indexTypeDashboard) - - batch := bluge.NewBatch() - batch.Delete(bluge.NewDocument(dashboardUID).ID()) - for _, panelID := range panelIDs { - batch.Delete(bluge.NewDocument(panelID).ID()) - } - - return writer.Batch(batch) -} - -func (i *searchIndex) removeFolder(_ context.Context, index *orgIndex, folderUID string) error { - ids, err := getDocsIDsByLocationPrefix(index, folderUID) - if err != nil { - return fmt.Errorf("error getting by location prefix: %w", err) - } - - batch := bluge.NewBatch() - batch.Delete(bluge.NewDocument(folderUID).ID()) - for _, id := range ids { - batch.Delete(bluge.NewDocument(id).ID()) - } - writer := index.writerForIndex(indexTypeDashboard) - return writer.Batch(batch) -} - -func stringInSlice(str string, slice []string) bool { - for _, s := range slice { - if s == str { - return true - } - } - return false -} - -func (i *searchIndex) updateDashboard(ctx context.Context, orgID int64, index *orgIndex, dash dashboard) error { - extendDoc := i.extender.GetDashboardExtender(orgID, dash.uid) - - writer := index.writerForIndex(indexTypeDashboard) - - var doc *bluge.Document - if dash.isFolder { - doc = getFolderDashboardDoc(dash) - if err := extendDoc(dash.uid, doc); err != nil { - return err - } - return writer.Update(doc.ID(), doc) - } - - batch := bluge.NewBatch() - - var folderUID string - if dash.folderID == 0 { - folderUID = folder.GeneralFolderUID - } else { - folderUID = dash.folderUID - } - - location := folderUID - doc = getNonFolderDashboardDoc(dash, location) - if err := extendDoc(dash.uid, doc); err != nil { - return err - } - - if location != "" { - location += "/" - } - location += dash.uid - panelDocs := getDashboardPanelDocs(dash, location) - actualPanelIDs := make([]string, 0, len(panelDocs)) - for _, panelDoc := range panelDocs { - actualPanelIDs = append(actualPanelIDs, string(panelDoc.ID().Term())) - batch.Update(panelDoc.ID(), panelDoc) - } - - indexedPanelIDs, err := getDashboardPanelIDs(index, location) - if err != nil { - return err - } - - for _, panelID := range indexedPanelIDs { - if !stringInSlice(panelID, actualPanelIDs) { - batch.Delete(bluge.NewDocument(panelID).ID()) - } - } - - batch.Update(doc.ID(), doc) - - return writer.Batch(batch) -} - -type sqlDashboardLoader struct { - sql db.DB - logger log.Logger - tracer tracing.Tracer - settings setting.SearchSettings -} - -func newSQLDashboardLoader(sql db.DB, tracer tracing.Tracer, settings setting.SearchSettings) *sqlDashboardLoader { - return &sqlDashboardLoader{sql: sql, logger: log.New("sqlDashboardLoader"), tracer: tracer, settings: settings} -} - -type dashboardsRes struct { - dashboards []*dashboardQueryResult - err error -} - -func (l sqlDashboardLoader) loadAllDashboards(ctx context.Context, limit int, orgID int64, dashboardUID string) chan *dashboardsRes { - ch := make(chan *dashboardsRes, 3) - - go func() { - defer close(ch) - - var lastID int64 - for { - select { - case <-ctx.Done(): - err := ctx.Err() - if err != nil { - ch <- &dashboardsRes{ - dashboards: nil, - err: err, - } - } - return - default: - } - - dashboardQueryCtx, dashboardQuerySpan := l.tracer.Start(ctx, "sqlDashboardLoader dashboardQuery", trace.WithAttributes( - attribute.Int64("orgID", orgID), - attribute.String("dashboardUID", dashboardUID), - attribute.Int64("lastID", lastID), - )) - - rows := make([]*dashboardQueryResult, 0, limit) - err := l.sql.WithDbSession(dashboardQueryCtx, func(sess *db.Session) error { - sess.Table("dashboard"). - Where("org_id = ?", orgID). - Where("deleted IS NULL") // don't index soft delete files - - if lastID > 0 { - sess.Where("id > ?", lastID) - } - - if dashboardUID != "" { - sess.Where("uid = ?", dashboardUID) - } - - sess.Cols("id", "uid", "is_folder", "folder_id", "folder_uid", "data", "slug", "created", "updated") - - sess.OrderBy("id ASC") - sess.Limit(limit) - - return sess.Find(&rows) - }) - - dashboardQuerySpan.End() - - if err != nil || len(rows) < limit || dashboardUID != "" { - ch <- &dashboardsRes{ - dashboards: rows, - err: err, - } - break - } - - ch <- &dashboardsRes{ - dashboards: rows, - } - - if len(rows) > 0 { - lastID = rows[len(rows)-1].Id - } - } - }() - - return ch -} - -func (l sqlDashboardLoader) LoadDashboards(ctx context.Context, orgID int64, dashboardUID string) ([]dashboard, error) { - ctx, span := l.tracer.Start(ctx, "sqlDashboardLoader LoadDashboards", trace.WithAttributes( - attribute.Int64("orgID", orgID), - )) - defer span.End() - - var dashboards []dashboard - - limit := 1 - - if dashboardUID == "" { - limit = l.settings.DashboardLoadingBatchSize - dashboards = make([]dashboard, 0, limit) - } - - loadDatasourceCtx, loadDatasourceSpan := l.tracer.Start(ctx, "sqlDashboardLoader LoadDatasourceLookup", trace.WithAttributes( - attribute.Int64("orgID", orgID), - )) - - // key will allow name or uid - lookup, err := kdash.LoadDatasourceLookup(loadDatasourceCtx, orgID, l.sql) - if err != nil { - loadDatasourceSpan.End() - return dashboards, err - } - loadDatasourceSpan.End() - - loadingDashboardCtx, cancelLoadingDashboardCtx := context.WithCancel(ctx) - defer cancelLoadingDashboardCtx() - - dashboardsChannel := l.loadAllDashboards(loadingDashboardCtx, limit, orgID, dashboardUID) - - for { - res, ok := <-dashboardsChannel - if res != nil && res.err != nil { - l.logger.Error("Error when loading dashboards", "error", err, "orgID", orgID, "dashboardUID", dashboardUID) - break - } - - if res == nil || !ok { - break - } - - rows := res.dashboards - - _, readDashboardSpan := l.tracer.Start(ctx, "sqlDashboardLoader readDashboard", trace.WithAttributes( - attribute.Int64("orgID", orgID), - attribute.Int("dashboardCount", len(rows)), - )) - - reader := kdash.NewStaticDashboardSummaryBuilder(lookup, false) - - for _, row := range rows { - summary, _, err := reader(ctx, row.Uid, row.Data) - if err != nil { - l.logger.Warn("Error indexing dashboard data", "error", err, "dashboardId", row.Id, "dashboardSlug", row.Slug) - // But append info anyway for now, since we possibly extracted useful information. - } - dashboards = append(dashboards, dashboard{ - id: row.Id, - uid: row.Uid, - isFolder: row.IsFolder, - folderID: row.FolderID, - folderUID: row.FolderUID, - slug: row.Slug, - created: row.Created, - updated: row.Updated, - summary: summary, - }) - } - readDashboardSpan.End() - } - - return dashboards, err -} - -type dashboardQueryResult struct { - Id int64 - Uid string - IsFolder bool `xorm:"is_folder"` - FolderID int64 `xorm:"folder_id"` - FolderUID string `xorm:"folder_uid"` - Slug string `xorm:"slug"` - Data []byte - Created time.Time - Updated time.Time -} diff --git a/pkg/services/searchV2/index_test.go b/pkg/services/searchV2/index_test.go deleted file mode 100644 index f7a84c0eb55..00000000000 --- a/pkg/services/searchV2/index_test.go +++ /dev/null @@ -1,735 +0,0 @@ -package searchV2 - -import ( - "context" - "fmt" - "path/filepath" - "testing" - - "github.com/blugelabs/bluge" - "github.com/grafana/grafana-plugin-sdk-go/backend" - "github.com/grafana/grafana-plugin-sdk-go/data" - "github.com/grafana/grafana-plugin-sdk-go/experimental" - "github.com/stretchr/testify/require" - - "github.com/grafana/grafana/pkg/infra/log" - "github.com/grafana/grafana/pkg/infra/tracing" - "github.com/grafana/grafana/pkg/services/featuremgmt" - "github.com/grafana/grafana/pkg/services/store" - "github.com/grafana/grafana/pkg/services/store/entity" - "github.com/grafana/grafana/pkg/setting" -) - -type testDashboardLoader struct { - dashboards []dashboard -} - -func (t *testDashboardLoader) LoadDashboards(_ context.Context, _ int64, _ string) ([]dashboard, error) { - return t.dashboards, nil -} - -var testLogger = log.New("index-test-logger") - -var testAllowAllFilter = func(kind entityKind, uid, parent string) bool { - return true -} - -var testDisallowAllFilter = func(kind entityKind, uid, parent string) bool { - return false -} - -var testOrgID int64 = 1 - -func initTestOrgIndexFromDashes(t *testing.T, dashboards []dashboard) *orgIndex { - t.Helper() - searchIdx := initTestIndexFromDashesExtended(t, dashboards, &NoopDocumentExtender{}) - return searchIdx.perOrgIndex[testOrgID] -} - -func initTestOrgIndexFromDashesExtended(t *testing.T, dashboards []dashboard, extender DocumentExtender) *orgIndex { - t.Helper() - searchIdx := initTestIndexFromDashesExtended(t, dashboards, extender) - return searchIdx.perOrgIndex[testOrgID] -} - -func initTestIndexFromDashes(t *testing.T, dashboards []dashboard) *searchIndex { - t.Helper() - return initTestIndexFromDashesExtended(t, dashboards, &NoopDocumentExtender{}) -} - -func initTestIndexFromDashesExtended(t *testing.T, dashboards []dashboard, extender DocumentExtender) *searchIndex { - t.Helper() - dashboardLoader := &testDashboardLoader{ - dashboards: dashboards, - } - index := newSearchIndex(dashboardLoader, &store.MockEntityEventsService{}, extender, tracing.InitializeTracerForTest(), featuremgmt.WithFeatures(), setting.SearchSettings{}) - require.NotNil(t, index) - numDashboards, err := index.buildOrgIndex(context.Background(), testOrgID) - require.NoError(t, err) - require.Equal(t, len(dashboardLoader.dashboards), numDashboards) - return index -} - -func checkSearchResponse(t *testing.T, fileName string, index *orgIndex, filter ResourceFilter, query DashboardQuery) { - t.Helper() - checkSearchResponseExtended(t, fileName, index, filter, query, &NoopQueryExtender{}) -} - -func checkSearchResponseExtended(t *testing.T, fileName string, index *orgIndex, filter ResourceFilter, query DashboardQuery, extender QueryExtender) { - t.Helper() - resp := doSearchQuery(context.Background(), testLogger, index, filter, query, extender, "/pfix") - experimental.CheckGoldenJSONResponse(t, "testdata", fileName, resp, true) -} - -func getFrameWithNames(resp *backend.DataResponse) *data.Frame { - if resp == nil || len(resp.Frames) == 0 { - return nil - } - - frame := resp.Frames[0] - nameField, idx := frame.FieldByName(documentFieldName) - if nameField.Len() == 0 || idx == -1 { - return nil - } - - scoreField, _ := frame.FieldByName("score") - return data.NewFrame("ordering frame", nameField, scoreField) -} - -func checkSearchResponseOrdering(t *testing.T, fileName string, index *orgIndex, filter ResourceFilter, query DashboardQuery) { - t.Helper() - checkSearchResponseOrderingExtended(t, fileName, index, filter, query, &NoopQueryExtender{}) -} - -func checkSearchResponseOrderingExtended(t *testing.T, fileName string, index *orgIndex, filter ResourceFilter, query DashboardQuery, extender QueryExtender) { - t.Helper() - query.Explain = true - resp := doSearchQuery(context.Background(), testLogger, index, filter, query, extender, "/pfix") - experimental.CheckGoldenJSONFrame(t, "testdata", fileName, getFrameWithNames(resp), true) -} - -var testDashboards = []dashboard{ - { - id: 1, - uid: "1", - summary: &entity.EntitySummary{ - Name: "test", - }, - }, - { - id: 2, - uid: "2", - summary: &entity.EntitySummary{ - Name: "boom", - }, - }, -} - -func TestDashboardIndex(t *testing.T) { - t.Run("basic-search", func(t *testing.T) { - index := initTestOrgIndexFromDashes(t, testDashboards) - checkSearchResponse(t, filepath.Base(t.Name()), index, testAllowAllFilter, - DashboardQuery{Query: "boom"}, - ) - }) - - t.Run("basic-filter", func(t *testing.T) { - index := initTestOrgIndexFromDashes(t, testDashboards) - checkSearchResponse(t, filepath.Base(t.Name()), index, testDisallowAllFilter, - DashboardQuery{Query: "boom"}, - ) - }) -} - -func TestDashboardIndexUpdates(t *testing.T) { - t.Run("dashboard-delete", func(t *testing.T) { - index := initTestIndexFromDashes(t, testDashboards) - orgIdx, ok := index.getOrgIndex(testOrgID) - require.True(t, ok) - err := index.removeDashboard(context.Background(), orgIdx, "2") - require.NoError(t, err) - checkSearchResponse(t, filepath.Base(t.Name()), orgIdx, testAllowAllFilter, - DashboardQuery{Query: "boom"}, - ) - }) - - t.Run("dashboard-create", func(t *testing.T) { - index := initTestIndexFromDashes(t, testDashboards) - orgIdx, ok := index.getOrgIndex(testOrgID) - require.True(t, ok) - - err := index.updateDashboard(context.Background(), testOrgID, orgIdx, dashboard{ - id: 3, - uid: "3", - summary: &entity.EntitySummary{ - Name: "created", - }, - }) - require.NoError(t, err) - - checkSearchResponse(t, filepath.Base(t.Name()), orgIdx, testAllowAllFilter, - DashboardQuery{Query: "created"}, - ) - }) - - t.Run("dashboard-update", func(t *testing.T) { - index := initTestIndexFromDashes(t, testDashboards) - orgIdx, ok := index.getOrgIndex(testOrgID) - require.True(t, ok) - - err := index.updateDashboard(context.Background(), testOrgID, orgIdx, dashboard{ - id: 2, - uid: "2", - summary: &entity.EntitySummary{ - Name: "nginx", - }, - }) - require.NoError(t, err) - - checkSearchResponse(t, filepath.Base(t.Name()), orgIdx, testAllowAllFilter, - DashboardQuery{Query: "nginx"}, - ) - }) -} - -var testSortDashboards = []dashboard{ - { - id: 1, - uid: "1", - summary: &entity.EntitySummary{ - Name: "a-test", - }, - }, - { - id: 2, - uid: "2", - summary: &entity.EntitySummary{ - Name: "z-test", - }, - }, -} - -type testExtender struct { - documentExtender DocumentExtender - queryExtender QueryExtender -} - -func (t *testExtender) GetDocumentExtender() DocumentExtender { - return t.documentExtender -} - -func (t *testExtender) GetQueryExtender() QueryExtender { - return t.queryExtender -} - -type testDocumentExtender struct { - ExtendDashboardFunc ExtendDashboardFunc -} - -func (t *testDocumentExtender) GetDashboardExtender(_ int64, _ ...string) ExtendDashboardFunc { - return t.ExtendDashboardFunc -} - -type testQueryExtender struct { - getFramer func(frame *data.Frame) FramerFunc -} - -func (t *testQueryExtender) GetFramer(frame *data.Frame) FramerFunc { - return t.getFramer(frame) -} - -func TestDashboardIndexSort(t *testing.T) { - var i float64 - extender := &testExtender{ - documentExtender: &testDocumentExtender{ - ExtendDashboardFunc: func(uid string, doc *bluge.Document) error { - doc.AddField(bluge.NewNumericField("test", i).StoreValue().Sortable()) - i++ - return nil - }, - }, - queryExtender: &testQueryExtender{ - getFramer: func(frame *data.Frame) FramerFunc { - testNum := data.NewFieldFromFieldType(data.FieldTypeFloat64, 0) - testNum.Name = "test num" - frame.Fields = append( - frame.Fields, - testNum, - ) - return func(field string, value []byte) { - if field == "test" { - if num, err := bluge.DecodeNumericFloat64(value); err == nil { - testNum.Append(num) - return - } - } - } - }, - }, - } - - t.Run("sort-asc", func(t *testing.T) { - index := initTestOrgIndexFromDashesExtended(t, testSortDashboards, extender.GetDocumentExtender()) - checkSearchResponseExtended(t, filepath.Base(t.Name()), index, testAllowAllFilter, - DashboardQuery{Query: "*", Sort: "test"}, extender.GetQueryExtender(), - ) - }) - - t.Run("sort-desc", func(t *testing.T) { - index := initTestOrgIndexFromDashesExtended(t, testSortDashboards, extender.GetDocumentExtender()) - checkSearchResponseExtended(t, filepath.Base(t.Name()), index, testAllowAllFilter, - DashboardQuery{Query: "*", Sort: "-test"}, extender.GetQueryExtender(), - ) - }) -} - -var testPrefixDashboards = []dashboard{ - { - id: 1, - uid: "1", - summary: &entity.EntitySummary{ - Name: "Archer Data System", - }, - }, - { - id: 2, - uid: "2", - summary: &entity.EntitySummary{ - Name: "Document Sync repo", - }, - }, -} - -func TestDashboardIndex_PrefixSearch(t *testing.T) { - t.Run("prefix-search-beginning", func(t *testing.T) { - index := initTestOrgIndexFromDashes(t, testPrefixDashboards) - checkSearchResponse(t, filepath.Base(t.Name()), index, testAllowAllFilter, - DashboardQuery{Query: "Arch"}, - ) - }) - - t.Run("prefix-search-middle", func(t *testing.T) { - index := initTestOrgIndexFromDashes(t, testPrefixDashboards) - checkSearchResponse(t, filepath.Base(t.Name()), index, testAllowAllFilter, - DashboardQuery{Query: "Syn"}, - ) - }) - - t.Run("prefix-search-beginning-lower", func(t *testing.T) { - index := initTestOrgIndexFromDashes(t, testPrefixDashboards) - checkSearchResponse(t, filepath.Base(t.Name()), index, testAllowAllFilter, - DashboardQuery{Query: "arch"}, - ) - }) - - t.Run("prefix-search-middle-lower", func(t *testing.T) { - index := initTestOrgIndexFromDashes(t, testPrefixDashboards) - checkSearchResponse(t, filepath.Base(t.Name()), index, testAllowAllFilter, - DashboardQuery{Query: "syn"}, - ) - }) -} - -func TestDashboardIndex_MultipleTokensInRow(t *testing.T) { - t.Run("multiple-tokens-beginning", func(t *testing.T) { - index := initTestOrgIndexFromDashes(t, testPrefixDashboards) - checkSearchResponse(t, filepath.Base(t.Name()), index, testAllowAllFilter, - DashboardQuery{Query: "Archer da"}, - ) - }) - - t.Run("multiple-tokens-beginning-lower", func(t *testing.T) { - index := initTestOrgIndexFromDashes(t, testPrefixDashboards) - checkSearchResponse(t, filepath.Base(t.Name()), index, testAllowAllFilter, - DashboardQuery{Query: "da archer"}, - ) - }) - - // Not sure it is great this matches, but - t.Run("multiple-tokens-middle", func(t *testing.T) { - index := initTestOrgIndexFromDashes(t, testPrefixDashboards) - checkSearchResponse(t, filepath.Base(t.Name()), index, testAllowAllFilter, - DashboardQuery{Query: "ar Da"}, - ) - }) - - t.Run("multiple-tokens-middle-lower", func(t *testing.T) { - index := initTestOrgIndexFromDashes(t, testPrefixDashboards) - checkSearchResponse(t, filepath.Base(t.Name()), index, testAllowAllFilter, - DashboardQuery{Query: "doc sy"}, - ) - }) -} - -var longPrefixDashboards = []dashboard{ - { - id: 1, - uid: "1", - summary: &entity.EntitySummary{ - Name: "EyjafjallajΓΆkull Eruption data", - }, - }, -} - -func TestDashboardIndex_PrefixNgramExceeded(t *testing.T) { - t.Run("prefix-search-ngram-exceeded", func(t *testing.T) { - index := initTestOrgIndexFromDashes(t, longPrefixDashboards) - checkSearchResponse(t, filepath.Base(t.Name()), index, testAllowAllFilter, - DashboardQuery{Query: "EyjafjallajΓΆku"}, - ) - }) -} - -var scatteredTokensDashboards = []dashboard{ - { - id: 1, - uid: "1", - summary: &entity.EntitySummary{ - Name: "Three can keep a secret, if two of them are dead (Benjamin Franklin)", - }, - }, - { - id: 3, - uid: "2", - summary: &entity.EntitySummary{ - Name: "A secret is powerful when it is empty (Umberto Eco)", - }, - }, -} - -func TestDashboardIndex_MultipleTokensScattered(t *testing.T) { - t.Run("scattered-tokens-match", func(t *testing.T) { - index := initTestOrgIndexFromDashes(t, scatteredTokensDashboards) - checkSearchResponse(t, filepath.Base(t.Name()), index, testAllowAllFilter, - DashboardQuery{Query: "dead secret"}, - ) - }) - t.Run("scattered-tokens-match-reversed", func(t *testing.T) { - index := initTestOrgIndexFromDashes(t, scatteredTokensDashboards) - checkSearchResponse(t, filepath.Base(t.Name()), index, testAllowAllFilter, - DashboardQuery{Query: "powerful secret"}, - ) - }) -} - -var dashboardsWithFolders = []dashboard{ - { - id: 1, - uid: "1", - isFolder: true, - summary: &entity.EntitySummary{ - Name: "My folder", - }, - }, - { - id: 2, - uid: "2", - folderID: 1, - folderUID: "1", - summary: &entity.EntitySummary{ - Name: "Dashboard in folder 1", - Nested: []*entity.EntitySummary{ - newNestedPanel(1, 2, "Panel 1"), - newNestedPanel(2, 2, "Panel 2"), - }, - }, - }, - { - id: 3, - uid: "3", - folderID: 1, - folderUID: "1", - summary: &entity.EntitySummary{ - Name: "Dashboard in folder 2", - Nested: []*entity.EntitySummary{ - newNestedPanel(3, 3, "Panel 3"), - }, - }, - }, - { - id: 4, - uid: "4", - summary: &entity.EntitySummary{ - Name: "One more dash", - Nested: []*entity.EntitySummary{ - newNestedPanel(4, 4, "Panel 4"), - }, - }, - }, -} - -func TestDashboardIndex_Folders(t *testing.T) { - t.Run("folders-indexed", func(t *testing.T) { - index := initTestOrgIndexFromDashes(t, dashboardsWithFolders) - checkSearchResponse(t, filepath.Base(t.Name()), index, testAllowAllFilter, - DashboardQuery{Query: "My folder", Kind: []string{string(entityKindFolder)}}, - ) - }) - t.Run("folders-dashboard-has-folder", func(t *testing.T) { - index := initTestOrgIndexFromDashes(t, dashboardsWithFolders) - // TODO: golden file compare does not work here. - resp := doSearchQuery(context.Background(), testLogger, index, testAllowAllFilter, - DashboardQuery{Query: "Dashboard in folder", Kind: []string{string(entityKindDashboard)}}, - &NoopQueryExtender{}, "") - custom, ok := resp.Frames[0].Meta.Custom.(*customMeta) - require.Equal(t, uint64(2), custom.Count) - require.True(t, ok, fmt.Sprintf("actual type: %T", resp.Frames[0].Meta.Custom)) - require.Equal(t, "/dashboards/f/1/", custom.Locations["1"].URL) - }) - t.Run("folders-dashboard-removed-on-folder-removed", func(t *testing.T) { - index := initTestIndexFromDashes(t, dashboardsWithFolders) - orgIdx, ok := index.getOrgIndex(testOrgID) - require.True(t, ok) - err := index.removeFolder(context.Background(), orgIdx, "1") - require.NoError(t, err) - // In response we expect one dashboard which does not belong to removed folder. - checkSearchResponse(t, filepath.Base(t.Name()), orgIdx, testAllowAllFilter, - DashboardQuery{Query: "dash", Kind: []string{string(entityKindDashboard)}}, - ) - }) - t.Run("folders-panels-removed-on-folder-removed", func(t *testing.T) { - index := initTestIndexFromDashes(t, dashboardsWithFolders) - orgIdx, ok := index.getOrgIndex(testOrgID) - require.True(t, ok) - err := index.removeFolder(context.Background(), orgIdx, "1") - require.NoError(t, err) - resp := doSearchQuery(context.Background(), testLogger, orgIdx, testAllowAllFilter, - DashboardQuery{Query: "Panel", Kind: []string{string(entityKindPanel)}}, - &NoopQueryExtender{}, "") - custom, ok := resp.Frames[0].Meta.Custom.(*customMeta) - require.True(t, ok) - require.Equal(t, uint64(1), custom.Count) // 1 panel which does not belong to dashboards in removed folder. - }) -} - -var dashboardsWithPanels = []dashboard{ - { - id: 1, - uid: "1", - summary: &entity.EntitySummary{ - Name: "My Dash", - Nested: []*entity.EntitySummary{ - newNestedPanel(1, 1, "Panel 1"), - newNestedPanel(2, 1, "Panel 2"), - }, - }, - }, -} - -func newNestedPanel(id, dashId int64, name string) *entity.EntitySummary { - summary := &entity.EntitySummary{ - Kind: "panel", - UID: fmt.Sprintf("%d#%d", dashId, id), - } - summary.Name = name - return summary -} - -func TestDashboardIndex_Panels(t *testing.T) { - t.Run("panels-indexed", func(t *testing.T) { - index := initTestOrgIndexFromDashes(t, dashboardsWithPanels) - // TODO: golden file compare does not work here. - resp := doSearchQuery( - context.Background(), testLogger, index, testAllowAllFilter, - DashboardQuery{Query: "Panel", Kind: []string{string(entityKindPanel)}}, - &NoopQueryExtender{}, "") - custom, ok := resp.Frames[0].Meta.Custom.(*customMeta) - require.True(t, ok, fmt.Sprintf("actual type: %T", resp.Frames[0].Meta.Custom)) - require.Equal(t, uint64(2), custom.Count) - require.Equal(t, "/d/1/", custom.Locations["1"].URL) - }) - t.Run("panels-panel-removed-on-dashboard-removed", func(t *testing.T) { - index := initTestIndexFromDashes(t, dashboardsWithPanels) - orgIdx, ok := index.getOrgIndex(testOrgID) - require.True(t, ok) - err := index.removeDashboard(context.Background(), orgIdx, "1") - require.NoError(t, err) - checkSearchResponse(t, filepath.Base(t.Name()), orgIdx, testAllowAllFilter, - DashboardQuery{Query: "Panel", Kind: []string{string(entityKindPanel)}}, - ) - }) -} - -var punctuationSplitNgramDashboards = []dashboard{ - { - id: 1, - uid: "1", - summary: &entity.EntitySummary{ - Name: "heat-torkel", - }, - }, - { - id: 2, - uid: "2", - summary: &entity.EntitySummary{ - Name: "topology heatmap", - }, - }, -} - -func TestDashboardIndex_PunctuationNgram(t *testing.T) { - t.Run("ngram-punctuation-split", func(t *testing.T) { - index := initTestOrgIndexFromDashes(t, punctuationSplitNgramDashboards) - checkSearchResponse(t, filepath.Base(t.Name()), index, testAllowAllFilter, - DashboardQuery{Query: "tork he"}, - ) - }) - - t.Run("ngram-simple", func(t *testing.T) { - index := initTestOrgIndexFromDashes(t, punctuationSplitNgramDashboards) - checkSearchResponse(t, filepath.Base(t.Name()), index, testAllowAllFilter, - DashboardQuery{Query: "hea"}, - ) - }) -} - -var camelCaseNgramDashboards = []dashboard{ - { - id: 1, - uid: "1", - summary: &entity.EntitySummary{ - Name: "heatTorkel", - }, - }, -} - -func TestDashboardIndex_CamelCaseNgram(t *testing.T) { - t.Run("ngram-camel-case-split", func(t *testing.T) { - index := initTestOrgIndexFromDashes(t, camelCaseNgramDashboards) - checkSearchResponse(t, filepath.Base(t.Name()), index, testAllowAllFilter, - DashboardQuery{Query: "tork"}, - ) - }) -} - -func dashboardsWithTitles(names ...string) []dashboard { - out := make([]dashboard, 0) - for i, name := range names { - no := int64(i + 1) - out = append(out, dashboard{ - id: no, - uid: fmt.Sprintf("%d", no), - summary: &entity.EntitySummary{ - Name: name, - }, - }) - } - - return out -} - -func TestDashboardIndex_MultiTermPrefixMatch(t *testing.T) { - var tests = []struct { - dashboards []dashboard - query string - }{ - { - dashboards: dashboardsWithTitles( - "Panel Tests - Bar Gauge 2", - "Prometheus 2.0", - "Prometheus 2.0 Stats", - "Prometheus 20.0", - "Prometheus Second Word", - "Prometheus Stats", - "dynamic (2)", - "prometheus histogram", - "prometheus histogram2", - "roci-simple-2", - "x not y", - ), - query: "Prometheus 2.", - }, - { - dashboards: dashboardsWithTitles( - "From AAA", - "Grafana Dev Overview & Home", - "Home automation", - "Prometheus 2.0", - "Prometheus 2.0 Stats", - "Prometheus 20.0", - "Prometheus Stats", - "Transforms - config from query", - "iot-testing", - "prom style with exemplars", - "prop history", - "simple frame", - "with-hide-from", - "xy broke", - ), - query: "Prome", - }, - { - dashboards: dashboardsWithTitles( - "Panel Tests - Bar Gauge 2", - "Prometheus 2.0", - "Prometheus 2.0 Stats", - "Prometheus 20.0", - "Prometheus Second Word", - "Prometheus Stats", - "dynamic (2)", - "prometheus histogram", - "prometheus histogram2", - "roci-simple-2", - "x not y", - ), - query: "Prometheus stat", - }, - { - dashboards: dashboardsWithTitles( - "Loki Tests - Bar Gauge 2", - "Loki 2.0", - "Loki 2.0 Stats", - "Loki 20.0", - "Loki Second Word", - "Loki Stats", - "dynamic (2)", - "Loki histogram", - "Loki histogram2", - "roci-simple-2", - "x not y", - ), - query: "Loki 2.", - }, - { - dashboards: dashboardsWithTitles( - "Loki Tests - Bar Gauge 2", - "Loki 2.0", - "Loki 2.0 Stats", - "Loki 20.0", - "Loki Second Word", - "Loki Stats", - "dynamic (2)", - "Loki histogram", - "Loki histogram2", - "roci-simple-2", - "x not y", - ), - query: "Lok", - }, - { - dashboards: dashboardsWithTitles( - "Loki Tests - Bar Gauge 2", - "Loki 2.0", - "Loki 2.0 Stats", - "Loki 20.0", - "Loki Second Word", - "Loki Stats", - "dynamic (2)", - "Loki histogram", - "Loki histogram2", - "roci-simple-2", - "x not y", - ), - query: "Loki stats", - }, - } - - for i, tt := range tests { - t.Run(fmt.Sprintf("ordering-tests-%d-[%s]", i+1, tt.query), func(t *testing.T) { - index := initTestOrgIndexFromDashes(t, tt.dashboards) - checkSearchResponseOrdering(t, filepath.Base(t.Name()), index, testAllowAllFilter, - DashboardQuery{Query: tt.query}, - ) - }) - } -} diff --git a/pkg/services/searchV2/ngram.go b/pkg/services/searchV2/ngram.go deleted file mode 100644 index 48c1e56fafb..00000000000 --- a/pkg/services/searchV2/ngram.go +++ /dev/null @@ -1,47 +0,0 @@ -package searchV2 - -import ( - "strings" - - "github.com/blugelabs/bluge/analysis" - "github.com/blugelabs/bluge/analysis/token" - "github.com/blugelabs/bluge/analysis/tokenizer" -) - -var punctuationReplacer *strings.Replacer - -func init() { - var punctuation = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~" - args := make([]string, 0, len(punctuation)*2) - for _, r := range punctuation { - args = append(args, string(r), " ") - } - punctuationReplacer = strings.NewReplacer(args...) -} - -type punctuationCharFilter struct{} - -func (t *punctuationCharFilter) Filter(input []byte) []byte { - return []byte(punctuationReplacer.Replace(string(input))) -} - -const ngramEdgeFilterMaxLength = 7 - -var ngramIndexAnalyzer = &analysis.Analyzer{ - CharFilters: []analysis.CharFilter{&punctuationCharFilter{}}, - Tokenizer: tokenizer.NewWhitespaceTokenizer(), - TokenFilters: []analysis.TokenFilter{ - token.NewCamelCaseFilter(), - token.NewLowerCaseFilter(), - token.NewEdgeNgramFilter(token.FRONT, 1, ngramEdgeFilterMaxLength), - }, -} - -var ngramQueryAnalyzer = &analysis.Analyzer{ - CharFilters: []analysis.CharFilter{&punctuationCharFilter{}}, - Tokenizer: tokenizer.NewWhitespaceTokenizer(), - TokenFilters: []analysis.TokenFilter{ - token.NewCamelCaseFilter(), - token.NewLowerCaseFilter(), - }, -} diff --git a/pkg/services/searchV2/ngram_test.go b/pkg/services/searchV2/ngram_test.go deleted file mode 100644 index 160a956db57..00000000000 --- a/pkg/services/searchV2/ngram_test.go +++ /dev/null @@ -1,61 +0,0 @@ -package searchV2 - -import ( - "reflect" - "testing" - - "github.com/stretchr/testify/require" -) - -func Test_punctuationCharFilter_Filter(t1 *testing.T) { - type args struct { - input []byte - } - tests := []struct { - name string - args args - want []byte - }{ - { - name: "1", - args: args{ - input: []byte("x-Rays"), - }, - want: []byte("x Rays"), - }, - { - name: "2", - args: args{ - input: []byte("x.Rays"), - }, - want: []byte("x Rays"), - }, - { - name: "3", - args: args{ - input: []byte("[x,Rays]"), - }, - want: []byte(" x Rays "), - }, - } - for _, tt := range tests { - t1.Run(tt.name, func(t1 *testing.T) { - t := &punctuationCharFilter{} - if got := t.Filter(tt.args.input); !reflect.DeepEqual(got, tt.want) { - t1.Errorf("Filter() = %v, want %v", string(got), string(tt.want)) - } - }) - } -} - -func TestNgramIndexAnalyzer(t *testing.T) { - stream := ngramIndexAnalyzer.Analyze([]byte("x-rays.and.xRays, and ΠΠ΅ΠΌΠ½ΠΎΠ³ΠΎΠšΠΈΡ€ΠΈΠ»Π»ΠΈΡ†Ρ‹")) - expectedTerms := []string{"x", "r", "ra", "ray", "rays", "a", "an", "and", "x", "r", "ra", "ray", "rays", "a", "an", "and", "Π½", "Π½Π΅", "Π½Π΅ΠΌ", "Π½Π΅ΠΌΠ½", "Π½Π΅ΠΌΠ½ΠΎ", "Π½Π΅ΠΌΠ½ΠΎΠ³", "Π½Π΅ΠΌΠ½ΠΎΠ³ΠΎ", "ΠΊ", "ΠΊΠΈ", "ΠΊΠΈΡ€", "ΠΊΠΈΡ€ΠΈ", "ΠΊΠΈΡ€ΠΈΠ»", "ΠΊΠΈΡ€ΠΈΠ»Π»", "ΠΊΠΈΡ€ΠΈΠ»Π»ΠΈ"} - - actualTerms := make([]string, 0, len(stream)) - for _, t := range stream { - actualTerms = append(actualTerms, string(t.Term)) - } - - require.Equal(t, expectedTerms, actualTerms) -} diff --git a/pkg/services/searchV2/object/testdata/gdev-walk-graph-gradient-area-fills.json b/pkg/services/searchV2/object/testdata/gdev-walk-graph-gradient-area-fills.json deleted file mode 100644 index f05b20ab297..00000000000 --- a/pkg/services/searchV2/object/testdata/gdev-walk-graph-gradient-area-fills.json +++ /dev/null @@ -1,90 +0,0 @@ -{ - "name": "Panel Tests - Graph - Gradient Area Fills", - "labels": { - "gdev": "", - "graph": "", - "panel-tests": "" - }, - "URL": "/d/graph-gradient-area-fills.json/panel-tests-graph-gradient-area-fills", - "nested": [ - { - "uid": "graph-gradient-area-fills.json#2", - "kind": "panel", - "name": "Req/s", - "URL": "/d/graph-gradient-area-fills.json/panel-tests-graph-gradient-area-fills?viewPanel=2", - "references": [ - { - "kind": "ds", - "type": "default.type", - "UID": "default.uid" - }, - { - "kind": "panel", - "type": "graph" - } - ] - }, - { - "uid": "graph-gradient-area-fills.json#11", - "kind": "panel", - "name": "Req/s", - "URL": "/d/graph-gradient-area-fills.json/panel-tests-graph-gradient-area-fills?viewPanel=11", - "references": [ - { - "kind": "ds", - "type": "default.type", - "UID": "default.uid" - }, - { - "kind": "panel", - "type": "graph" - } - ] - }, - { - "uid": "graph-gradient-area-fills.json#7", - "kind": "panel", - "name": "Memory", - "URL": "/d/graph-gradient-area-fills.json/panel-tests-graph-gradient-area-fills?viewPanel=7", - "references": [ - { - "kind": "ds", - "type": "default.type", - "UID": "default.uid" - }, - { - "kind": "panel", - "type": "graph" - } - ] - }, - { - "uid": "graph-gradient-area-fills.json#10", - "kind": "panel", - "name": "Req/s", - "URL": "/d/graph-gradient-area-fills.json/panel-tests-graph-gradient-area-fills?viewPanel=10", - "references": [ - { - "kind": "ds", - "type": "default.type", - "UID": "default.uid" - }, - { - "kind": "panel", - "type": "graph" - } - ] - } - ], - "references": [ - { - "kind": "ds", - "type": "default.type", - "UID": "default.uid" - }, - { - "kind": "panel", - "type": "graph" - } - ] -} \ No newline at end of file diff --git a/pkg/services/searchV2/object/testdata/gdev-walk-graph-shared-tooltips.json b/pkg/services/searchV2/object/testdata/gdev-walk-graph-shared-tooltips.json deleted file mode 100644 index 98b3755c13a..00000000000 --- a/pkg/services/searchV2/object/testdata/gdev-walk-graph-shared-tooltips.json +++ /dev/null @@ -1,178 +0,0 @@ -{ - "name": "Panel Tests - shared tooltips", - "labels": { - "gdev": "", - "graph-ng": "", - "panel-tests": "" - }, - "URL": "/d/graph-shared-tooltips.json/panel-tests-shared-tooltips", - "nested": [ - { - "uid": "graph-shared-tooltips.json#4", - "kind": "panel", - "name": "two units", - "URL": "/d/graph-shared-tooltips.json/panel-tests-shared-tooltips?viewPanel=4", - "references": [ - { - "kind": "ds", - "type": "default.type", - "UID": "default.uid" - }, - { - "kind": "panel", - "type": "timeseries" - } - ] - }, - { - "uid": "graph-shared-tooltips.json#13", - "kind": "panel", - "name": "Speed vs Temperature (XY)", - "URL": "/d/graph-shared-tooltips.json/panel-tests-shared-tooltips?viewPanel=13", - "references": [ - { - "kind": "ds", - "type": "default.type", - "UID": "default.uid" - }, - { - "kind": "panel", - "type": "xychart" - }, - { - "kind": "transform", - "type": "organize" - }, - { - "kind": "transform", - "type": "seriesToColumns" - } - ] - }, - { - "uid": "graph-shared-tooltips.json#2", - "kind": "panel", - "name": "Cursor info", - "URL": "/d/graph-shared-tooltips.json/panel-tests-shared-tooltips?viewPanel=2", - "references": [ - { - "kind": "ds", - "type": "default.type", - "UID": "default.uid" - }, - { - "kind": "panel", - "type": "debug" - } - ] - }, - { - "uid": "graph-shared-tooltips.json#5", - "kind": "panel", - "name": "Only temperature", - "URL": "/d/graph-shared-tooltips.json/panel-tests-shared-tooltips?viewPanel=5", - "references": [ - { - "kind": "ds", - "type": "default.type", - "UID": "default.uid" - }, - { - "kind": "panel", - "type": "timeseries" - } - ] - }, - { - "uid": "graph-shared-tooltips.json#9", - "kind": "panel", - "name": "Only Speed", - "URL": "/d/graph-shared-tooltips.json/panel-tests-shared-tooltips?viewPanel=9", - "references": [ - { - "kind": "ds", - "type": "default.type", - "UID": "default.uid" - }, - { - "kind": "panel", - "type": "timeseries" - } - ] - }, - { - "uid": "graph-shared-tooltips.json#11", - "kind": "panel", - "name": "Panel Title", - "URL": "/d/graph-shared-tooltips.json/panel-tests-shared-tooltips?viewPanel=11", - "references": [ - { - "kind": "ds", - "type": "default.type", - "UID": "default.uid" - }, - { - "kind": "panel", - "type": "timeseries" - } - ] - }, - { - "uid": "graph-shared-tooltips.json#8", - "kind": "panel", - "name": "flot panel (temperature)", - "URL": "/d/graph-shared-tooltips.json/panel-tests-shared-tooltips?viewPanel=8", - "references": [ - { - "kind": "ds", - "type": "default.type", - "UID": "default.uid" - }, - { - "kind": "panel", - "type": "graph" - } - ] - }, - { - "uid": "graph-shared-tooltips.json#10", - "kind": "panel", - "name": "flot panel (no units)", - "URL": "/d/graph-shared-tooltips.json/panel-tests-shared-tooltips?viewPanel=10", - "references": [ - { - "kind": "ds", - "type": "default.type", - "UID": "default.uid" - }, - { - "kind": "panel", - "type": "graph" - } - ] - } - ], - "references": [ - { - "kind": "ds", - "type": "default.type", - "UID": "default.uid" - }, - { - "kind": "panel", - "type": "debug" - }, - { - "kind": "panel", - "type": "graph" - }, - { - "kind": "panel", - "type": "timeseries" - }, - { - "kind": "panel", - "type": "xychart" - } - ] -} \ No newline at end of file diff --git a/pkg/services/searchV2/object/testdata/gdev-walk-graph-time-regions.json b/pkg/services/searchV2/object/testdata/gdev-walk-graph-time-regions.json deleted file mode 100644 index 5285623011d..00000000000 --- a/pkg/services/searchV2/object/testdata/gdev-walk-graph-time-regions.json +++ /dev/null @@ -1,107 +0,0 @@ -{ - "name": "Panel Tests - Graph Time Regions", - "labels": { - "gdev": "", - "graph": "", - "panel-tests": "" - }, - "URL": "/d/graph-time-regions.json/panel-tests-graph-time-regions", - "nested": [ - { - "uid": "graph-time-regions.json#2", - "kind": "panel", - "name": "Business Hours", - "URL": "/d/graph-time-regions.json/panel-tests-graph-time-regions?viewPanel=2", - "references": [ - { - "kind": "ds", - "type": "default.type", - "UID": "default.uid" - }, - { - "kind": "panel", - "type": "graph" - } - ] - }, - { - "uid": "graph-time-regions.json#4", - "kind": "panel", - "name": "Sunday's 20-23", - "URL": "/d/graph-time-regions.json/panel-tests-graph-time-regions?viewPanel=4", - "references": [ - { - "kind": "ds", - "type": "default.type", - "UID": "default.uid" - }, - { - "kind": "panel", - "type": "graph" - } - ] - }, - { - "uid": "graph-time-regions.json#3", - "kind": "panel", - "name": "Each day of week", - "URL": "/d/graph-time-regions.json/panel-tests-graph-time-regions?viewPanel=3", - "references": [ - { - "kind": "ds", - "type": "default.type", - "UID": "default.uid" - }, - { - "kind": "panel", - "type": "graph" - } - ] - }, - { - "uid": "graph-time-regions.json#5", - "kind": "panel", - "name": "05:00", - "URL": "/d/graph-time-regions.json/panel-tests-graph-time-regions?viewPanel=5", - "references": [ - { - "kind": "ds", - "type": "default.type", - "UID": "default.uid" - }, - { - "kind": "panel", - "type": "graph" - } - ] - }, - { - "uid": "graph-time-regions.json#7", - "kind": "panel", - "name": "From 22:00 to 00:30 (crossing midnight)", - "URL": "/d/graph-time-regions.json/panel-tests-graph-time-regions?viewPanel=7", - "references": [ - { - "kind": "ds", - "type": "default.type", - "UID": "default.uid" - }, - { - "kind": "panel", - "type": "graph" - } - ] - } - ], - "references": [ - { - "kind": "ds", - "type": "default.type", - "UID": "default.uid" - }, - { - "kind": "panel", - "type": "graph" - } - ] -} \ No newline at end of file diff --git a/pkg/services/searchV2/object/testdata/gdev-walk-graph_tests.json b/pkg/services/searchV2/object/testdata/gdev-walk-graph_tests.json deleted file mode 100644 index 87123dd0a45..00000000000 --- a/pkg/services/searchV2/object/testdata/gdev-walk-graph_tests.json +++ /dev/null @@ -1,377 +0,0 @@ -{ - "name": "Panel Tests - Graph", - "labels": { - "gdev": "", - "graph": "", - "panel-tests": "" - }, - "URL": "/d/graph_tests.json/panel-tests-graph", - "nested": [ - { - "uid": "graph_tests.json#1", - "kind": "panel", - "name": "No Data Points Warning", - "URL": "/d/graph_tests.json/panel-tests-graph?viewPanel=1", - "references": [ - { - "kind": "ds", - "type": "default.type", - "UID": "default.uid" - }, - { - "kind": "panel", - "type": "graph" - } - ] - }, - { - "uid": "graph_tests.json#2", - "kind": "panel", - "name": "Datapoints Outside Range Warning", - "URL": "/d/graph_tests.json/panel-tests-graph?viewPanel=2", - "references": [ - { - "kind": "ds", - "type": "default.type", - "UID": "default.uid" - }, - { - "kind": "panel", - "type": "graph" - } - ] - }, - { - "uid": "graph_tests.json#3", - "kind": "panel", - "name": "Random walk series", - "URL": "/d/graph_tests.json/panel-tests-graph?viewPanel=3", - "references": [ - { - "kind": "ds", - "type": "default.type", - "UID": "default.uid" - }, - { - "kind": "panel", - "type": "graph" - } - ] - }, - { - "uid": "graph_tests.json#4", - "kind": "panel", - "name": "Millisecond res x-axis and tooltip", - "URL": "/d/graph_tests.json/panel-tests-graph?viewPanel=4", - "references": [ - { - "kind": "ds", - "type": "default.type", - "UID": "default.uid" - }, - { - "kind": "panel", - "type": "graph" - } - ] - }, - { - "uid": "graph_tests.json#6", - "kind": "panel", - "URL": "/d/graph_tests.json/panel-tests-graph?viewPanel=6", - "references": [ - { - "kind": "ds", - "type": "default.type", - "UID": "default.uid" - }, - { - "kind": "panel", - "type": "text" - } - ] - }, - { - "uid": "graph_tests.json#5", - "kind": "panel", - "name": "2 yaxis and axis labels", - "URL": "/d/graph_tests.json/panel-tests-graph?viewPanel=5", - "references": [ - { - "kind": "ds", - "type": "default.type", - "UID": "default.uid" - }, - { - "kind": "panel", - "type": "graph" - } - ] - }, - { - "uid": "graph_tests.json#7", - "kind": "panel", - "URL": "/d/graph_tests.json/panel-tests-graph?viewPanel=7", - "references": [ - { - "kind": "ds", - "type": "default.type", - "UID": "default.uid" - }, - { - "kind": "panel", - "type": "text" - } - ] - }, - { - "uid": "graph_tests.json#8", - "kind": "panel", - "name": "null value connected", - "URL": "/d/graph_tests.json/panel-tests-graph?viewPanel=8", - "references": [ - { - "kind": "ds", - "type": "default.type", - "UID": "default.uid" - }, - { - "kind": "panel", - "type": "graph" - } - ] - }, - { - "uid": "graph_tests.json#10", - "kind": "panel", - "name": "null value null as zero", - "URL": "/d/graph_tests.json/panel-tests-graph?viewPanel=10", - "references": [ - { - "kind": "ds", - "type": "default.type", - "UID": "default.uid" - }, - { - "kind": "panel", - "type": "graph" - } - ] - }, - { - "uid": "graph_tests.json#13", - "kind": "panel", - "URL": "/d/graph_tests.json/panel-tests-graph?viewPanel=13", - "references": [ - { - "kind": "ds", - "type": "default.type", - "UID": "default.uid" - }, - { - "kind": "panel", - "type": "text" - } - ] - }, - { - "uid": "graph_tests.json#9", - "kind": "panel", - "name": "Stacking value ontop of nulls", - "URL": "/d/graph_tests.json/panel-tests-graph?viewPanel=9", - "references": [ - { - "kind": "ds", - "type": "default.type", - "UID": "default.uid" - }, - { - "kind": "panel", - "type": "graph" - } - ] - }, - { - "uid": "graph_tests.json#14", - "kind": "panel", - "URL": "/d/graph_tests.json/panel-tests-graph?viewPanel=14", - "references": [ - { - "kind": "ds", - "type": "default.type", - "UID": "default.uid" - }, - { - "kind": "panel", - "type": "text" - } - ] - }, - { - "uid": "graph_tests.json#12", - "kind": "panel", - "name": "Stacking all series null segment", - "URL": "/d/graph_tests.json/panel-tests-graph?viewPanel=12", - "references": [ - { - "kind": "ds", - "type": "default.type", - "UID": "default.uid" - }, - { - "kind": "panel", - "type": "graph" - } - ] - }, - { - "uid": "graph_tests.json#15", - "kind": "panel", - "URL": "/d/graph_tests.json/panel-tests-graph?viewPanel=15", - "references": [ - { - "kind": "ds", - "type": "default.type", - "UID": "default.uid" - }, - { - "kind": "panel", - "type": "text" - } - ] - }, - { - "uid": "graph_tests.json#21", - "kind": "panel", - "name": "Null between points", - "URL": "/d/graph_tests.json/panel-tests-graph?viewPanel=21", - "references": [ - { - "kind": "ds", - "type": "default.type", - "UID": "default.uid" - }, - { - "kind": "panel", - "type": "graph" - } - ] - }, - { - "uid": "graph_tests.json#22", - "kind": "panel", - "URL": "/d/graph_tests.json/panel-tests-graph?viewPanel=22", - "references": [ - { - "kind": "ds", - "type": "default.type", - "UID": "default.uid" - }, - { - "kind": "panel", - "type": "text" - } - ] - }, - { - "uid": "graph_tests.json#20", - "kind": "panel", - "name": "Legend Table Single Series Should Take Minimum Height", - "URL": "/d/graph_tests.json/panel-tests-graph?viewPanel=20", - "references": [ - { - "kind": "ds", - "type": "default.type", - "UID": "default.uid" - }, - { - "kind": "panel", - "type": "graph" - } - ] - }, - { - "uid": "graph_tests.json#16", - "kind": "panel", - "name": "Legend Table No Scroll Visible", - "URL": "/d/graph_tests.json/panel-tests-graph?viewPanel=16", - "references": [ - { - "kind": "ds", - "type": "default.type", - "UID": "default.uid" - }, - { - "kind": "panel", - "type": "graph" - } - ] - }, - { - "uid": "graph_tests.json#17", - "kind": "panel", - "name": "Legend Table Should Scroll", - "URL": "/d/graph_tests.json/panel-tests-graph?viewPanel=17", - "references": [ - { - "kind": "ds", - "type": "default.type", - "UID": "default.uid" - }, - { - "kind": "panel", - "type": "graph" - } - ] - }, - { - "uid": "graph_tests.json#18", - "kind": "panel", - "name": "Legend Table No Scroll Visible", - "URL": "/d/graph_tests.json/panel-tests-graph?viewPanel=18", - "references": [ - { - "kind": "ds", - "type": "default.type", - "UID": "default.uid" - }, - { - "kind": "panel", - "type": "graph" - } - ] - }, - { - "uid": "graph_tests.json#19", - "kind": "panel", - "name": "Legend Table No Scroll Visible", - "URL": "/d/graph_tests.json/panel-tests-graph?viewPanel=19", - "references": [ - { - "kind": "ds", - "type": "default.type", - "UID": "default.uid" - }, - { - "kind": "panel", - "type": "graph" - } - ] - } - ], - "references": [ - { - "kind": "ds", - "type": "default.type", - "UID": "default.uid" - }, - { - "kind": "panel", - "type": "graph" - }, - { - "kind": "panel", - "type": "text" - } - ] -} \ No newline at end of file diff --git a/pkg/services/searchV2/object/testdata/gdev-walk-graph_y_axis.json b/pkg/services/searchV2/object/testdata/gdev-walk-graph_y_axis.json deleted file mode 100644 index 851395df0c2..00000000000 --- a/pkg/services/searchV2/object/testdata/gdev-walk-graph_y_axis.json +++ /dev/null @@ -1,174 +0,0 @@ -{ - "name": "Panel Tests - Graph - Y axis ticks", - "labels": { - "gdev": "", - "panel-tests": "" - }, - "URL": "/d/graph_y_axis.json/panel-tests-graph-y-axis-ticks", - "nested": [ - { - "uid": "graph_y_axis.json#7", - "kind": "panel", - "name": "Data from 0 - 10K (unit short)", - "URL": "/d/graph_y_axis.json/panel-tests-graph-y-axis-ticks?viewPanel=7", - "references": [ - { - "kind": "ds", - "type": "default.type", - "UID": "default.uid" - }, - { - "kind": "panel", - "type": "graph" - } - ] - }, - { - "uid": "graph_y_axis.json#5", - "kind": "panel", - "name": "Data from 0 - 10K (unit bytes metric)", - "URL": "/d/graph_y_axis.json/panel-tests-graph-y-axis-ticks?viewPanel=5", - "references": [ - { - "kind": "ds", - "type": "default.type", - "UID": "default.uid" - }, - { - "kind": "panel", - "type": "graph" - } - ] - }, - { - "uid": "graph_y_axis.json#4", - "kind": "panel", - "name": "Data from 0 - 10K (unit bytes IEC)", - "URL": "/d/graph_y_axis.json/panel-tests-graph-y-axis-ticks?viewPanel=4", - "references": [ - { - "kind": "ds", - "type": "default.type", - "UID": "default.uid" - }, - { - "kind": "panel", - "type": "graph" - } - ] - }, - { - "uid": "graph_y_axis.json#2", - "kind": "panel", - "name": "Data from 0 - 10K (unit short)", - "URL": "/d/graph_y_axis.json/panel-tests-graph-y-axis-ticks?viewPanel=2", - "references": [ - { - "kind": "ds", - "type": "default.type", - "UID": "default.uid" - }, - { - "kind": "panel", - "type": "graph" - } - ] - }, - { - "uid": "graph_y_axis.json#3", - "kind": "panel", - "name": "Data from 0.0002 - 0.001 (unit short)", - "URL": "/d/graph_y_axis.json/panel-tests-graph-y-axis-ticks?viewPanel=3", - "references": [ - { - "kind": "ds", - "type": "default.type", - "UID": "default.uid" - }, - { - "kind": "panel", - "type": "graph" - } - ] - }, - { - "uid": "graph_y_axis.json#6", - "kind": "panel", - "name": "Data from 12000 - 30000 (unit ms)", - "URL": "/d/graph_y_axis.json/panel-tests-graph-y-axis-ticks?viewPanel=6", - "references": [ - { - "kind": "ds", - "type": "default.type", - "UID": "default.uid" - }, - { - "kind": "panel", - "type": "graph" - } - ] - }, - { - "uid": "graph_y_axis.json#9", - "kind": "panel", - "name": "Data from 0 - 1B (unit short)", - "URL": "/d/graph_y_axis.json/panel-tests-graph-y-axis-ticks?viewPanel=9", - "references": [ - { - "kind": "ds", - "type": "default.type", - "UID": "default.uid" - }, - { - "kind": "panel", - "type": "graph" - } - ] - }, - { - "uid": "graph_y_axis.json#10", - "kind": "panel", - "name": "Data from 0 - 1B (unit bytes)", - "URL": "/d/graph_y_axis.json/panel-tests-graph-y-axis-ticks?viewPanel=10", - "references": [ - { - "kind": "ds", - "type": "default.type", - "UID": "default.uid" - }, - { - "kind": "panel", - "type": "graph" - } - ] - }, - { - "uid": "graph_y_axis.json#8", - "kind": "panel", - "name": "Data from 12000 - 30000 (unit ms)", - "URL": "/d/graph_y_axis.json/panel-tests-graph-y-axis-ticks?viewPanel=8", - "references": [ - { - "kind": "ds", - "type": "default.type", - "UID": "default.uid" - }, - { - "kind": "panel", - "type": "graph" - } - ] - } - ], - "references": [ - { - "kind": "ds", - "type": "default.type", - "UID": "default.uid" - }, - { - "kind": "panel", - "type": "graph" - } - ] -} \ No newline at end of file diff --git a/pkg/services/searchV2/search_service_mock.go b/pkg/services/searchV2/search_service_mock.go deleted file mode 100644 index 920b0621291..00000000000 --- a/pkg/services/searchV2/search_service_mock.go +++ /dev/null @@ -1,136 +0,0 @@ -// Code generated by mockery v2.53.4. DO NOT EDIT. - -package searchV2 - -import ( - context "context" - - backend "github.com/grafana/grafana-plugin-sdk-go/backend" - - mock "github.com/stretchr/testify/mock" - - user "github.com/grafana/grafana/pkg/services/user" -) - -// MockSearchService is an autogenerated mock type for the SearchService type -type MockSearchService struct { - mock.Mock -} - -// DoDashboardQuery provides a mock function with given fields: ctx, _a1, orgId, query -func (_m *MockSearchService) DoDashboardQuery(ctx context.Context, _a1 *backend.User, orgId int64, query DashboardQuery) *backend.DataResponse { - ret := _m.Called(ctx, _a1, orgId, query) - - if len(ret) == 0 { - panic("no return value specified for DoDashboardQuery") - } - - var r0 *backend.DataResponse - if rf, ok := ret.Get(0).(func(context.Context, *backend.User, int64, DashboardQuery) *backend.DataResponse); ok { - r0 = rf(ctx, _a1, orgId, query) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*backend.DataResponse) - } - } - - return r0 -} - -// IsDisabled provides a mock function with no fields -func (_m *MockSearchService) IsDisabled() bool { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for IsDisabled") - } - - var r0 bool - if rf, ok := ret.Get(0).(func() bool); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(bool) - } - - return r0 -} - -// IsReady provides a mock function with given fields: ctx, orgId -func (_m *MockSearchService) IsReady(ctx context.Context, orgId int64) IsSearchReadyResponse { - ret := _m.Called(ctx, orgId) - - if len(ret) == 0 { - panic("no return value specified for IsReady") - } - - var r0 IsSearchReadyResponse - if rf, ok := ret.Get(0).(func(context.Context, int64) IsSearchReadyResponse); ok { - r0 = rf(ctx, orgId) - } else { - r0 = ret.Get(0).(IsSearchReadyResponse) - } - - return r0 -} - -// RegisterDashboardIndexExtender provides a mock function with given fields: ext -func (_m *MockSearchService) RegisterDashboardIndexExtender(ext DashboardIndexExtender) { - _m.Called(ext) -} - -// Run provides a mock function with given fields: ctx -func (_m *MockSearchService) Run(ctx context.Context) error { - ret := _m.Called(ctx) - - if len(ret) == 0 { - panic("no return value specified for Run") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context) error); ok { - r0 = rf(ctx) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// TriggerReIndex provides a mock function with no fields -func (_m *MockSearchService) TriggerReIndex() { - _m.Called() -} - -// doDashboardQuery provides a mock function with given fields: ctx, _a1, orgId, query -func (_m *MockSearchService) doDashboardQuery(ctx context.Context, _a1 *user.SignedInUser, orgId int64, query DashboardQuery) *backend.DataResponse { - ret := _m.Called(ctx, _a1, orgId, query) - - if len(ret) == 0 { - panic("no return value specified for doDashboardQuery") - } - - var r0 *backend.DataResponse - if rf, ok := ret.Get(0).(func(context.Context, *user.SignedInUser, int64, DashboardQuery) *backend.DataResponse); ok { - r0 = rf(ctx, _a1, orgId, query) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*backend.DataResponse) - } - } - - return r0 -} - -// NewMockSearchService creates a new instance of MockSearchService. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -// The first argument is typically a *testing.T value. -func NewMockSearchService(t interface { - mock.TestingT - Cleanup(func()) -}) *MockSearchService { - mock := &MockSearchService{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/pkg/services/searchV2/service.go b/pkg/services/searchV2/service.go deleted file mode 100644 index 855c89a90e4..00000000000 --- a/pkg/services/searchV2/service.go +++ /dev/null @@ -1,289 +0,0 @@ -package searchV2 - -import ( - "context" - "errors" - "fmt" - "time" - - "github.com/grafana/grafana-plugin-sdk-go/backend" - "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/promauto" - "go.opentelemetry.io/otel" - - "github.com/grafana/grafana/pkg/infra/db" - "github.com/grafana/grafana/pkg/infra/log" - "github.com/grafana/grafana/pkg/infra/tracing" - "github.com/grafana/grafana/pkg/registry" - "github.com/grafana/grafana/pkg/services/accesscontrol" - "github.com/grafana/grafana/pkg/services/featuremgmt" - "github.com/grafana/grafana/pkg/services/folder" - "github.com/grafana/grafana/pkg/services/org" - "github.com/grafana/grafana/pkg/services/store" - "github.com/grafana/grafana/pkg/services/user" - "github.com/grafana/grafana/pkg/setting" -) - -var ( - namespace = "grafana" - subsystem = "search" - dashboardSearchNotServedRequestsCounter = promauto.NewCounterVec( - prometheus.CounterOpts{ - Namespace: namespace, - Subsystem: subsystem, - Name: "dashboard_search_requests_not_served_total", - Help: "A counter for dashboard search requests that could not be served due to an ongoing search engine indexing", - }, - []string{"reason"}, - ) - dashboardSearchFailureRequestsCounter = promauto.NewCounterVec( - prometheus.CounterOpts{ - Namespace: namespace, - Subsystem: subsystem, - Name: "dashboard_search_failures_total", - Help: "A counter for failed dashboard search requests", - }, - []string{"reason"}, - ) - dashboardSearchSuccessRequestsDuration = promauto.NewHistogram( - prometheus.HistogramOpts{ - Name: "dashboard_search_successes_duration_seconds", - Buckets: []float64{.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10, 25, 50, 100}, - Namespace: namespace, - Subsystem: subsystem, - }) - dashboardSearchFailureRequestsDuration = promauto.NewHistogram( - prometheus.HistogramOpts{ - Name: "dashboard_search_failures_duration_seconds", - Buckets: []float64{.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10, 25, 50, 100}, - Namespace: namespace, - Subsystem: subsystem, - }) - tracer = otel.Tracer("github.com/grafana/grafana/pkg/services/searchv2") -) - -type StandardSearchService struct { - registry.BackgroundService - - cfg *setting.Cfg - sql db.DB - auth FutureAuthService // eventually injected from elsewhere - ac accesscontrol.Service - orgService org.Service - userService user.Service - - logger log.Logger - dashboardIndex *searchIndex - extender DashboardIndexExtender - reIndexCh chan struct{} - features featuremgmt.FeatureToggles -} - -func (s *StandardSearchService) IsReady(ctx context.Context, orgId int64) IsSearchReadyResponse { - return s.dashboardIndex.isInitialized(ctx, orgId) -} - -func ProvideService(cfg *setting.Cfg, sql db.DB, entityEventStore store.EntityEventsService, - ac accesscontrol.Service, tracer tracing.Tracer, features featuremgmt.FeatureToggles, orgService org.Service, - userService user.Service, folderService folder.Service) SearchService { - extender := &NoopExtender{} - logger := log.New("searchV2") - s := &StandardSearchService{ - cfg: cfg, - sql: sql, - ac: ac, - auth: &simpleAuthService{ - sql: sql, - ac: ac, - folderService: folderService, - logger: logger, - }, - dashboardIndex: newSearchIndex( - newSQLDashboardLoader(sql, tracer, cfg.Search), - entityEventStore, - extender.GetDocumentExtender(), - tracer, - features, - cfg.Search, - ), - logger: logger, - extender: extender, - reIndexCh: make(chan struct{}, 1), - orgService: orgService, - userService: userService, - features: features, - } - return s -} - -func (s *StandardSearchService) IsDisabled() bool { - //nolint:staticcheck // not yet migrated to OpenFeature - return !s.features.IsEnabledGlobally(featuremgmt.FlagPanelTitleSearch) -} - -func (s *StandardSearchService) Run(ctx context.Context) error { - ctx, span := tracer.Start(ctx, "searchv2.Run") - defer span.End() - orgQuery := &org.SearchOrgsQuery{} - result, err := s.orgService.Search(ctx, orgQuery) - if err != nil { - return fmt.Errorf("can't get org list: %w", err) - } - orgIDs := make([]int64, 0, len(result)) - for _, org := range result { - orgIDs = append(orgIDs, org.ID) - } - return s.dashboardIndex.run(ctx, orgIDs, s.reIndexCh) -} - -func (s *StandardSearchService) TriggerReIndex() { - select { - case s.reIndexCh <- struct{}{}: - default: - // channel is full => re-index will happen soon anyway. - } -} - -func (s *StandardSearchService) RegisterDashboardIndexExtender(ext DashboardIndexExtender) { - s.extender = ext - s.dashboardIndex.extender = ext.GetDocumentExtender() -} - -func (s *StandardSearchService) getUser(ctx context.Context, backendUser *backend.User, orgId int64) (*user.SignedInUser, error) { - ctx, span := tracer.Start(ctx, "searchv2.getUser") - defer span.End() - // TODO: get user & user's permissions from the request context - - var usr *user.SignedInUser - if s.cfg.Anonymous.Enabled && backendUser.Email == "" && backendUser.Login == "" { - getOrg := org.GetOrgByNameQuery{Name: s.cfg.Anonymous.OrgName} - orga, err := s.orgService.GetByName(ctx, &getOrg) - if err != nil { - s.logger.Error("Anonymous access organization error.", "org_name", s.cfg.Anonymous.OrgName, "error", err) - return nil, err - } - - usr = &user.SignedInUser{ - OrgID: orga.ID, - OrgName: orga.Name, - OrgRole: org.RoleType(s.cfg.Anonymous.OrgRole), - IsAnonymous: true, - } - } else { - getSignedInUserQuery := &user.GetSignedInUserQuery{ - Login: backendUser.Login, - Email: backendUser.Email, - OrgID: orgId, - } - var err error - usr, err = s.userService.GetSignedInUser(ctx, getSignedInUserQuery) - if err != nil { - s.logger.Error("Error while retrieving user", "error", err, "email", backendUser.Email, "login", getSignedInUserQuery.Login) - return nil, errors.New("auth error") - } - - if usr == nil { - s.logger.Error("No user found", "email", backendUser.Email) - return nil, errors.New("auth error") - } - } - - if usr.Permissions == nil { - usr.Permissions = make(map[int64]map[string][]string) - } - - if _, ok := usr.Permissions[orgId]; ok { - // permissions as part of the `s.sql.GetSignedInUser` query - return early - return usr, nil - } - - // TODO: ensure this is cached - permissions, err := s.ac.GetUserPermissions(ctx, usr, - accesscontrol.Options{ReloadCache: false}) - if err != nil { - s.logger.Error("Failed to retrieve user permissions", "error", err, "email", backendUser.Email) - return nil, errors.New("auth error") - } - - usr.Permissions[orgId] = accesscontrol.GroupScopesByActionContext(ctx, permissions) - return usr, nil -} - -func (s *StandardSearchService) DoDashboardQuery(ctx context.Context, user *backend.User, orgID int64, q DashboardQuery) *backend.DataResponse { - ctx, span := tracer.Start(ctx, "searchv2.DoDashboardQuery") - defer span.End() - start := time.Now() - - signedInUser, err := s.getUser(ctx, user, orgID) - - if err != nil { - dashboardSearchFailureRequestsCounter.With(prometheus.Labels{ - "reason": "get_user_error", - }).Inc() - - duration := time.Since(start).Seconds() - dashboardSearchFailureRequestsDuration.Observe(duration) - - return &backend.DataResponse{Error: err} - } - - query := s.doDashboardQuery(ctx, signedInUser, orgID, q) - - duration := time.Since(start).Seconds() - if query.Error != nil { - dashboardSearchFailureRequestsDuration.Observe(duration) - } else { - dashboardSearchSuccessRequestsDuration.Observe(duration) - } - - return query -} - -func (s *StandardSearchService) doDashboardQuery(ctx context.Context, signedInUser *user.SignedInUser, orgID int64, q DashboardQuery) *backend.DataResponse { - ctx, span := tracer.Start(ctx, "searchv2.doDashboardQuery") - defer span.End() - rsp := &backend.DataResponse{} - - filter, err := s.auth.GetDashboardReadFilter(ctx, orgID, signedInUser) - if err != nil { - dashboardSearchFailureRequestsCounter.With(prometheus.Labels{ - "reason": "get_dashboard_filter_error", - }).Inc() - rsp.Error = err - return rsp - } - - index, err := s.dashboardIndex.getOrCreateOrgIndex(ctx, orgID) - if err != nil { - dashboardSearchFailureRequestsCounter.With(prometheus.Labels{ - "reason": "get_index_error", - }).Inc() - rsp.Error = err - return rsp - } - - err = s.dashboardIndex.sync(ctx) - if err != nil { - dashboardSearchFailureRequestsCounter.With(prometheus.Labels{ - "reason": "dashboard_index_sync_error", - }).Inc() - rsp.Error = err - return rsp - } - - response := doSearchQuery(ctx, s.logger, index, filter, q, s.extender.GetQueryExtender(q), s.cfg.AppSubURL) - - if q.WithAllowedActions { - if err := s.addAllowedActionsField(ctx, orgID, signedInUser, response); err != nil { - s.logger.Error("Error when adding the allowedActions field", "err", err) - } - } - - if response.Error != nil { - dashboardSearchFailureRequestsCounter.With(prometheus.Labels{ - "reason": "search_query_error", - }).Inc() - } - - return response -} diff --git a/pkg/services/searchV2/service_bench_test.go b/pkg/services/searchV2/service_bench_test.go deleted file mode 100644 index 778e7bd2bf8..00000000000 --- a/pkg/services/searchV2/service_bench_test.go +++ /dev/null @@ -1,214 +0,0 @@ -package searchV2 - -import ( - "context" - "fmt" - "testing" - "time" - - "github.com/stretchr/testify/require" - - "github.com/grafana/grafana/pkg/infra/db" - "github.com/grafana/grafana/pkg/infra/tracing" - "github.com/grafana/grafana/pkg/services/accesscontrol/actest" - "github.com/grafana/grafana/pkg/services/dashboards" - "github.com/grafana/grafana/pkg/services/featuremgmt" - "github.com/grafana/grafana/pkg/services/folder/foldertest" - "github.com/grafana/grafana/pkg/services/org" - "github.com/grafana/grafana/pkg/services/org/orgtest" - "github.com/grafana/grafana/pkg/services/store" - "github.com/grafana/grafana/pkg/services/user" - "github.com/grafana/grafana/pkg/setting" - "github.com/grafana/grafana/pkg/tests/testsuite" -) - -func TestMain(m *testing.M) { - testsuite.Run(m) -} - -// setupBenchEnv will set up a database with folderCount folders and dashboardsPerFolder dashboards per folder -// It will also set up and run the search service -// and create a signed in user object with explicit permissions on each dashboard and folder. -func setupBenchEnv(b *testing.B, folderCount, dashboardsPerFolder int) (*StandardSearchService, *user.SignedInUser, error) { - sqlStore := db.InitTestDB(b) - err := populateDB(folderCount, dashboardsPerFolder, sqlStore) - require.NoError(b, err, "error when populating the database") - - // load all dashboards and folders - dbLoadingBatchSize := (dashboardsPerFolder + 1) * folderCount - cfg := &setting.Cfg{Search: setting.SearchSettings{DashboardLoadingBatchSize: dbLoadingBatchSize}} - features := featuremgmt.WithFeatures() - orgSvc := &orgtest.FakeOrgService{ - ExpectedOrgs: []*org.OrgDTO{{ID: 1}}, - } - searchService, ok := ProvideService(cfg, sqlStore, store.NewDummyEntityEventsService(), actest.FakeService{}, - tracing.InitializeTracerForTest(), features, orgSvc, nil, foldertest.NewFakeService()).(*StandardSearchService) - require.True(b, ok) - - err = runSearchService(searchService) - require.NoError(b, err, "error when running search service") - - user := getSignedInUser(folderCount, dashboardsPerFolder) - - return searchService, user, nil -} - -// Returns a signed in user object with permissions on all dashboards and folders -func getSignedInUser(folderCount, dashboardsPerFolder int) *user.SignedInUser { - folderScopes := make([]string, folderCount) - for i := 1; i <= folderCount; i++ { - folderScopes[i-1] = dashboards.ScopeFoldersProvider.GetResourceScopeUID(fmt.Sprintf("folder%d", i)) - } - - dashScopes := make([]string, folderCount*dashboardsPerFolder) - for i := folderCount + 1; i <= (folderCount * (dashboardsPerFolder + 1)); i++ { - dashScopes[i-(folderCount+1)] = dashboards.ScopeDashboardsProvider.GetResourceScopeUID(fmt.Sprintf("dashboard%d", i)) - } - - user := &user.SignedInUser{ - UserID: 1, - OrgID: 1, - Permissions: map[int64]map[string][]string{ - 1: { - dashboards.ActionDashboardsRead: dashScopes, - dashboards.ActionFoldersRead: folderScopes, - }, - }, - } - - return user -} - -// Runs initial indexing of search service -func runSearchService(searchService *StandardSearchService) error { - if err := searchService.dashboardIndex.buildInitialIndexes(context.Background(), []int64{int64(1)}); err != nil { - return err - } - searchService.dashboardIndex.initialIndexingComplete = true - - // Required for sync that is called during dashboard search - go func() { - for { - doneCh := <-searchService.dashboardIndex.syncCh - close(doneCh) - } - }() - - return nil -} - -// Populates database with dashboards and folders -func populateDB(folderCount, dashboardsPerFolder int, sqlStore db.DB) error { - // Insert folders - offset := 1 - if errInsert := actest.ConcurrentBatch(actest.Concurrency, folderCount, actest.BatchSize, func(start, end int) error { - n := end - start - folders := make([]dashboards.Dashboard, 0, n) - now := time.Now() - - for u := start; u < end; u++ { - folderID := int64(u + offset) - folders = append(folders, dashboards.Dashboard{ - ID: folderID, - UID: fmt.Sprintf("folder%v", folderID), - Title: fmt.Sprintf("folder%v", folderID), - IsFolder: true, - OrgID: 1, - Created: now, - Updated: now, - }) - } - - err := sqlStore.WithDbSession(context.Background(), func(sess *db.Session) error { - if _, err := sess.Insert(folders); err != nil { - return err - } - return nil - }) - return err - }); errInsert != nil { - return errInsert - } - - // Insert dashboards - offset += folderCount - if errInsert := actest.ConcurrentBatch(actest.Concurrency, dashboardsPerFolder*folderCount, actest.BatchSize, func(start, end int) error { - n := end - start - dbs := make([]dashboards.Dashboard, 0, n) - now := time.Now() - - for u := start; u < end; u++ { - dashID := int64(u + offset) - folderUID := fmt.Sprintf("folder%v", int64((u+offset)%folderCount+1)) - dbs = append(dbs, dashboards.Dashboard{ - ID: dashID, - UID: fmt.Sprintf("dashboard%v", dashID), - Title: fmt.Sprintf("dashboard%v", dashID), - IsFolder: false, - FolderUID: folderUID, - OrgID: 1, - Created: now, - Updated: now, - }) - } - - err := sqlStore.WithDbSession(context.Background(), func(sess *db.Session) error { - if _, err := sess.Insert(dbs); err != nil { - return err - } - return nil - }) - return err - }); errInsert != nil { - return errInsert - } - - return nil -} - -func benchSearchV2(b *testing.B, folderCount, dashboardsPerFolder int) { - searchService, testUser, err := setupBenchEnv(b, folderCount, dashboardsPerFolder) - require.NoError(b, err) - - b.ResetTimer() - - expectedResultCount := (dashboardsPerFolder + 1) * folderCount - for n := 0; n < b.N; n++ { - result := searchService.doDashboardQuery(context.Background(), testUser, 1, DashboardQuery{Limit: expectedResultCount}) - require.NoError(b, result.Error) - require.NotZero(b, len(result.Frames)) - for _, field := range result.Frames[0].Fields { - if field.Name == "uid" { - require.Equal(b, expectedResultCount, field.Len()) - break - } - } - } -} - -// Test with some dashboards and some folders -func BenchmarkSearchV2_10_10(b *testing.B) { - benchSearchV2(b, 10, 10) -} // ~0.0002 s/op -func BenchmarkSearchV2_10_100(b *testing.B) { - benchSearchV2(b, 10, 100) -} // ~0.002 s/op - -// Test with many dashboards and only one folder -func BenchmarkSearchV2_1_1k(b *testing.B) { - benchSearchV2(b, 1, 1000) -} // ~0.002 s/op -func BenchmarkSearchV2_1_10k(b *testing.B) { - benchSearchV2(b, 1, 10000) -} // ~0.019 s/op - -// Test with a large number of dashboards and folders -func BenchmarkSearchV2_100_100(b *testing.B) { - benchSearchV2(b, 100, 100) -} // ~0.02 s/op -func BenchmarkSearchV2_100_1k(b *testing.B) { - benchSearchV2(b, 100, 1000) -} // ~0.22 s/op -func BenchmarkSearchV2_1k_100(b *testing.B) { - benchSearchV2(b, 1000, 100) -} // ~0.22 s/op diff --git a/pkg/services/searchV2/stub.go b/pkg/services/searchV2/stub.go deleted file mode 100644 index f3edd473fe6..00000000000 --- a/pkg/services/searchV2/stub.go +++ /dev/null @@ -1,56 +0,0 @@ -package searchV2 - -import ( - "context" - - "github.com/grafana/grafana-plugin-sdk-go/backend" - "github.com/grafana/grafana-plugin-sdk-go/data" - - "github.com/grafana/grafana/pkg/services/user" -) - -type stubSearchService struct { -} - -func (s *stubSearchService) doDashboardQuery(ctx context.Context, user *user.SignedInUser, orgId int64, query DashboardQuery) *backend.DataResponse { - return s.DoDashboardQuery(ctx, nil, orgId, query) -} - -func (s *stubSearchService) IsReady(ctx context.Context, orgId int64) IsSearchReadyResponse { - return IsSearchReadyResponse{} -} - -func (s *stubSearchService) IsDisabled() bool { - return true -} - -func (s *stubSearchService) TriggerReIndex() { - // noop. -} - -func NewStubSearchService() SearchService { - return &stubSearchService{} -} - -func (s *stubSearchService) DoDashboardQuery(ctx context.Context, user *backend.User, orgId int64, query DashboardQuery) *backend.DataResponse { - rsp := &backend.DataResponse{} - - // dashboards - fid := data.NewFieldFromFieldType(data.FieldTypeInt64, 0) - uid := data.NewFieldFromFieldType(data.FieldTypeString, 0) - - fid.Append(int64(2)) - uid.Append("hello") - - rsp.Frames = append(rsp.Frames, data.NewFrame("dasboards", fid, uid)) - - return rsp -} - -func (s *stubSearchService) RegisterDashboardIndexExtender(ext DashboardIndexExtender) { - // noop -} - -func (s *stubSearchService) Run(_ context.Context) error { - return nil -} diff --git a/pkg/services/searchV2/substring_query.go b/pkg/services/searchV2/substring_query.go deleted file mode 100644 index 338ae74d798..00000000000 --- a/pkg/services/searchV2/substring_query.go +++ /dev/null @@ -1,102 +0,0 @@ -// based on https://github.com/blugelabs/bluge/blob/57414197005148539c5dc5db8ab581594969df79/query.go#L1407-L1482, license: -// Copyright (c) 2020 Couchbase, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package searchV2 - -import ( - "strings" - - "github.com/blugelabs/bluge/search" - "github.com/blugelabs/bluge/search/searcher" - "github.com/blugelabs/bluge/search/similarity" -) - -type boost float64 - -func (b *boost) Value() float64 { - if b == nil { - return 1 - } - return float64(*b) -} - -type SubstringQuery struct { - substring string - field string - boost *boost - scorer search.Scorer -} - -func NewSubstringQuery(wildcard string) *SubstringQuery { - return &SubstringQuery{ - substring: wildcard, - } -} - -// Wildcard returns the substring being queried -func (q *SubstringQuery) Wildcard() string { - return q.substring -} - -func (q *SubstringQuery) SetBoost(b float64) *SubstringQuery { - boostVal := boost(b) - q.boost = &boostVal - return q -} - -func (q *SubstringQuery) Boost() float64 { - return q.boost.Value() -} - -func (q *SubstringQuery) SetField(f string) *SubstringQuery { - q.field = f - return q -} - -func (q *SubstringQuery) Field() string { - return q.field -} - -var regexpEscaper = strings.NewReplacer( - // characters in the substring that must - // be escaped in the regexp - "+", `\+`, - "*", `\*`, - "(", `\(`, - ")", `\)`, - "^", `\^`, - "$", `\$`, - ".", `\.`, - "{", `\{`, - "}", `\}`, - "[", `\[`, - "]", `\]`, - `|`, `\|`, - `\`, `\\`) - -func (q *SubstringQuery) Searcher(i search.Reader, options search.SearcherOptions) (search.Searcher, error) { - field := q.field - if q.field == "" { - field = options.DefaultSearchField - } - - regexpString := ".*" + regexpEscaper.Replace(q.substring) + ".*" - return searcher.NewRegexpStringSearcher(i, regexpString, field, - q.boost.Value(), q.scorer, similarity.NewCompositeSumScorer(), options) -} - -func (q *SubstringQuery) Validate() error { - return nil // real validation delayed until searcher constructor -} diff --git a/pkg/services/searchV2/testdata/allowed_actions_scope_all.golden.jsonc b/pkg/services/searchV2/testdata/allowed_actions_scope_all.golden.jsonc deleted file mode 100644 index eb93e6f75f0..00000000000 --- a/pkg/services/searchV2/testdata/allowed_actions_scope_all.golden.jsonc +++ /dev/null @@ -1,329 +0,0 @@ -// 🌟 This was machine generated. Do not edit. 🌟 -// -// Frame[0] { -// "type": "search-results", -// "typeVersion": [ -// 0, -// 0 -// ], -// "custom": { -// "count": 106, -// "locationInfo": { -// "yboVMzb7z": { -// "kind": "folder", -// "name": "gdev dashboards", -// "url": "/dashboards/f/yboVMzb7z/gdev-dashboards" -// } -// }, -// "sortBy": "name_sort" -// } -// } -// Name: Query results -// Dimensions: 9 Fields by 4 Rows -// +----------------+----------------+-------------------------+------------------+--------------------------------------+--------------------------+---------------------------+----------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -// | Name: kind | Name: uid | Name: name | Name: panel_type | Name: url | Name: tags | Name: ds_uid | Name: location | Name: allowed_actions | -// | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | -// | Type: []string | Type: []string | Type: []string | Type: []string | Type: []string | Type: []*json.RawMessage | Type: []json.RawMessage | Type: []string | Type: []json.RawMessage | -// +----------------+----------------+-------------------------+------------------+--------------------------------------+--------------------------+---------------------------+----------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -// | folder | ujaM1h6nz | abc2 | | /dashboards/f/ujaM1h6nz/abc2 | null | [] | | [{"kind":"folder","uid":"ujaM1h6nz","actions":["folders.permissions:read","folders.permissions:write","folders:create","folders:delete","folders:read","folders:write"]}] | -// | dashboard | 7MeksYbmk | Alerting with TestData | | /d/7MeksYbmk/alerting-with-testdata | [ | [ | yboVMzb7z | [{"kind":"dashboard","uid":"7MeksYbmk","actions":["dashboards.permissions:read","dashboards.permissions:write","dashboards:create","dashboards:delete","dashboards:read","dashboards:write"]},{"kind":"ds","uid":"datasource-1","actions":["datasources.id:read","datasources.permissions:read","datasources.permissions:write","datasources:delete","datasources:explore","datasources:query","datasources:read","datasources:write"]}] | -// | | | | | | "gdev", | "datasource-1" | | | -// | | | | | | "alerting" | ] | | | -// | | | | | | ] | | | | -// | dashboard | vmie2cmWz | Bar Gauge Demo | | /d/vmie2cmWz/bar-gauge-demo | [ | [ | yboVMzb7z | [{"kind":"dashboard","uid":"vmie2cmWz","actions":["dashboards.permissions:read","dashboards.permissions:write","dashboards:create","dashboards:delete","dashboards:read","dashboards:write"]},{"kind":"ds","uid":"datasource-2","actions":["datasources.id:read","datasources.permissions:read","datasources.permissions:write","datasources:delete","datasources:explore","datasources:query","datasources:read","datasources:write"]},{"kind":"ds","uid":"datasource-3","actions":["datasources.id:read","datasources.permissions:read","datasources.permissions:write","datasources:delete","datasources:explore","datasources:query","datasources:read","datasources:write"]},{"kind":"ds","uid":"datasource-4","actions":["datasources.id:read","datasources.permissions:read","datasources.permissions:write","datasources:delete","datasources:explore","datasources:query","datasources:read","datasources:write"]}] | -// | | | | | | "gdev", | "datasource-2", | | | -// | | | | | | "demo" | "datasource-3", | | | -// | | | | | | ] | "datasource-4" | | | -// | | | | | | | ] | | | -// | dashboard | xMsQdBfWz | Bar Gauge Demo Unfilled | | /d/xMsQdBfWz/bar-gauge-demo-unfilled | [ | [] | yboVMzb7z | [{"kind":"dashboard","uid":"xMsQdBfWz","actions":["dashboards.permissions:read","dashboards.permissions:write","dashboards:create","dashboards:delete","dashboards:read","dashboards:write"]}] | -// | | | | | | "gdev", | | | | -// | | | | | | "demo" | | | | -// | | | | | | ] | | | | -// +----------------+----------------+-------------------------+------------------+--------------------------------------+--------------------------+---------------------------+----------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -// -// -// 🌟 This was machine generated. Do not edit. 🌟 -{ - "status": 200, - "frames": [ - { - "schema": { - "name": "Query results", - "refId": "Search", - "meta": { - "type": "search-results", - "typeVersion": [ - 0, - 0 - ], - "custom": { - "count": 106, - "locationInfo": { - "yboVMzb7z": { - "kind": "folder", - "name": "gdev dashboards", - "url": "/dashboards/f/yboVMzb7z/gdev-dashboards" - } - }, - "sortBy": "name_sort" - } - }, - "fields": [ - { - "name": "kind", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "uid", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "name", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "panel_type", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "url", - "type": "string", - "typeInfo": { - "frame": "string" - }, - "config": { - "links": [ - { - "title": "link", - "url": "${__value.text}" - } - ] - } - }, - { - "name": "tags", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage", - "nullable": true - } - }, - { - "name": "ds_uid", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage" - } - }, - { - "name": "location", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "allowed_actions", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage" - } - } - ] - }, - "data": { - "values": [ - [ - "folder", - "dashboard", - "dashboard", - "dashboard" - ], - [ - "ujaM1h6nz", - "7MeksYbmk", - "vmie2cmWz", - "xMsQdBfWz" - ], - [ - "abc2", - "Alerting with TestData", - "Bar Gauge Demo", - "Bar Gauge Demo Unfilled" - ], - [ - "", - "", - "", - "" - ], - [ - "/dashboards/f/ujaM1h6nz/abc2", - "/d/7MeksYbmk/alerting-with-testdata", - "/d/vmie2cmWz/bar-gauge-demo", - "/d/xMsQdBfWz/bar-gauge-demo-unfilled" - ], - [ - null, - [ - "gdev", - "alerting" - ], - [ - "gdev", - "demo" - ], - [ - "gdev", - "demo" - ] - ], - [ - [], - [ - "datasource-1" - ], - [ - "datasource-2", - "datasource-3", - "datasource-4" - ], - [] - ], - [ - "", - "yboVMzb7z", - "yboVMzb7z", - "yboVMzb7z" - ], - [ - [ - { - "kind": "folder", - "uid": "ujaM1h6nz", - "actions": [ - "folders.permissions:read", - "folders.permissions:write", - "folders:create", - "folders:delete", - "folders:read", - "folders:write" - ] - } - ], - [ - { - "kind": "dashboard", - "uid": "7MeksYbmk", - "actions": [ - "dashboards.permissions:read", - "dashboards.permissions:write", - "dashboards:create", - "dashboards:delete", - "dashboards:read", - "dashboards:write" - ] - }, - { - "kind": "ds", - "uid": "datasource-1", - "actions": [ - "datasources.id:read", - "datasources.permissions:read", - "datasources.permissions:write", - "datasources:delete", - "datasources:explore", - "datasources:query", - "datasources:read", - "datasources:write" - ] - } - ], - [ - { - "kind": "dashboard", - "uid": "vmie2cmWz", - "actions": [ - "dashboards.permissions:read", - "dashboards.permissions:write", - "dashboards:create", - "dashboards:delete", - "dashboards:read", - "dashboards:write" - ] - }, - { - "kind": "ds", - "uid": "datasource-2", - "actions": [ - "datasources.id:read", - "datasources.permissions:read", - "datasources.permissions:write", - "datasources:delete", - "datasources:explore", - "datasources:query", - "datasources:read", - "datasources:write" - ] - }, - { - "kind": "ds", - "uid": "datasource-3", - "actions": [ - "datasources.id:read", - "datasources.permissions:read", - "datasources.permissions:write", - "datasources:delete", - "datasources:explore", - "datasources:query", - "datasources:read", - "datasources:write" - ] - }, - { - "kind": "ds", - "uid": "datasource-4", - "actions": [ - "datasources.id:read", - "datasources.permissions:read", - "datasources.permissions:write", - "datasources:delete", - "datasources:explore", - "datasources:query", - "datasources:read", - "datasources:write" - ] - } - ], - [ - { - "kind": "dashboard", - "uid": "xMsQdBfWz", - "actions": [ - "dashboards.permissions:read", - "dashboards.permissions:write", - "dashboards:create", - "dashboards:delete", - "dashboards:read", - "dashboards:write" - ] - } - ] - ] - ] - } - } - ] -} \ No newline at end of file diff --git a/pkg/services/searchV2/testdata/allowed_actions_scope_uids.golden.jsonc b/pkg/services/searchV2/testdata/allowed_actions_scope_uids.golden.jsonc deleted file mode 100644 index 4ef6ffdbad3..00000000000 --- a/pkg/services/searchV2/testdata/allowed_actions_scope_uids.golden.jsonc +++ /dev/null @@ -1,273 +0,0 @@ -// 🌟 This was machine generated. Do not edit. 🌟 -// -// Frame[0] { -// "type": "search-results", -// "typeVersion": [ -// 0, -// 0 -// ], -// "custom": { -// "count": 106, -// "locationInfo": { -// "yboVMzb7z": { -// "kind": "folder", -// "name": "gdev dashboards", -// "url": "/dashboards/f/yboVMzb7z/gdev-dashboards" -// } -// }, -// "sortBy": "name_sort" -// } -// } -// Name: Query results -// Dimensions: 9 Fields by 4 Rows -// +----------------+----------------+-------------------------+------------------+--------------------------------------+--------------------------+---------------------------+----------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -// | Name: kind | Name: uid | Name: name | Name: panel_type | Name: url | Name: tags | Name: ds_uid | Name: location | Name: allowed_actions | -// | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | -// | Type: []string | Type: []string | Type: []string | Type: []string | Type: []string | Type: []*json.RawMessage | Type: []json.RawMessage | Type: []string | Type: []json.RawMessage | -// +----------------+----------------+-------------------------+------------------+--------------------------------------+--------------------------+---------------------------+----------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -// | folder | ujaM1h6nz | abc2 | | /dashboards/f/ujaM1h6nz/abc2 | null | [] | | [{"kind":"folder","uid":"ujaM1h6nz","actions":["folders:read"]}] | -// | dashboard | 7MeksYbmk | Alerting with TestData | | /d/7MeksYbmk/alerting-with-testdata | [ | [ | yboVMzb7z | [{"kind":"dashboard","uid":"7MeksYbmk","actions":["dashboards:write"]},{"kind":"ds","uid":"datasource-1","actions":[]}] | -// | | | | | | "gdev", | "datasource-1" | | | -// | | | | | | "alerting" | ] | | | -// | | | | | | ] | | | | -// | dashboard | vmie2cmWz | Bar Gauge Demo | | /d/vmie2cmWz/bar-gauge-demo | [ | [ | yboVMzb7z | [{"kind":"dashboard","uid":"vmie2cmWz","actions":[]},{"kind":"ds","uid":"datasource-2","actions":["datasources:read"]},{"kind":"ds","uid":"datasource-3","actions":["datasources:read"]},{"kind":"ds","uid":"datasource-4","actions":[]}] | -// | | | | | | "gdev", | "datasource-2", | | | -// | | | | | | "demo" | "datasource-3", | | | -// | | | | | | ] | "datasource-4" | | | -// | | | | | | | ] | | | -// | dashboard | xMsQdBfWz | Bar Gauge Demo Unfilled | | /d/xMsQdBfWz/bar-gauge-demo-unfilled | [ | [] | yboVMzb7z | [{"kind":"dashboard","uid":"xMsQdBfWz","actions":[]}] | -// | | | | | | "gdev", | | | | -// | | | | | | "demo" | | | | -// | | | | | | ] | | | | -// +----------------+----------------+-------------------------+------------------+--------------------------------------+--------------------------+---------------------------+----------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -// -// -// 🌟 This was machine generated. Do not edit. 🌟 -{ - "status": 200, - "frames": [ - { - "schema": { - "name": "Query results", - "refId": "Search", - "meta": { - "type": "search-results", - "typeVersion": [ - 0, - 0 - ], - "custom": { - "count": 106, - "locationInfo": { - "yboVMzb7z": { - "kind": "folder", - "name": "gdev dashboards", - "url": "/dashboards/f/yboVMzb7z/gdev-dashboards" - } - }, - "sortBy": "name_sort" - } - }, - "fields": [ - { - "name": "kind", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "uid", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "name", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "panel_type", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "url", - "type": "string", - "typeInfo": { - "frame": "string" - }, - "config": { - "links": [ - { - "title": "link", - "url": "${__value.text}" - } - ] - } - }, - { - "name": "tags", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage", - "nullable": true - } - }, - { - "name": "ds_uid", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage" - } - }, - { - "name": "location", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "allowed_actions", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage" - } - } - ] - }, - "data": { - "values": [ - [ - "folder", - "dashboard", - "dashboard", - "dashboard" - ], - [ - "ujaM1h6nz", - "7MeksYbmk", - "vmie2cmWz", - "xMsQdBfWz" - ], - [ - "abc2", - "Alerting with TestData", - "Bar Gauge Demo", - "Bar Gauge Demo Unfilled" - ], - [ - "", - "", - "", - "" - ], - [ - "/dashboards/f/ujaM1h6nz/abc2", - "/d/7MeksYbmk/alerting-with-testdata", - "/d/vmie2cmWz/bar-gauge-demo", - "/d/xMsQdBfWz/bar-gauge-demo-unfilled" - ], - [ - null, - [ - "gdev", - "alerting" - ], - [ - "gdev", - "demo" - ], - [ - "gdev", - "demo" - ] - ], - [ - [], - [ - "datasource-1" - ], - [ - "datasource-2", - "datasource-3", - "datasource-4" - ], - [] - ], - [ - "", - "yboVMzb7z", - "yboVMzb7z", - "yboVMzb7z" - ], - [ - [ - { - "kind": "folder", - "uid": "ujaM1h6nz", - "actions": [ - "folders:read" - ] - } - ], - [ - { - "kind": "dashboard", - "uid": "7MeksYbmk", - "actions": [ - "dashboards:write" - ] - }, - { - "kind": "ds", - "uid": "datasource-1", - "actions": [] - } - ], - [ - { - "kind": "dashboard", - "uid": "vmie2cmWz", - "actions": [] - }, - { - "kind": "ds", - "uid": "datasource-2", - "actions": [ - "datasources:read" - ] - }, - { - "kind": "ds", - "uid": "datasource-3", - "actions": [ - "datasources:read" - ] - }, - { - "kind": "ds", - "uid": "datasource-4", - "actions": [] - } - ], - [ - { - "kind": "dashboard", - "uid": "xMsQdBfWz", - "actions": [] - } - ] - ] - ] - } - } - ] -} \ No newline at end of file diff --git a/pkg/services/searchV2/testdata/basic-filter.jsonc b/pkg/services/searchV2/testdata/basic-filter.jsonc deleted file mode 100644 index a5e0a619ad3..00000000000 --- a/pkg/services/searchV2/testdata/basic-filter.jsonc +++ /dev/null @@ -1,122 +0,0 @@ -// 🌟 This was machine generated. Do not edit. 🌟 -// -// Frame[0] { -// "type": "search-results", -// "typeVersion": [ -// 0, -// 0 -// ], -// "custom": { -// "count": 0 -// } -// } -// Name: Query results -// Dimensions: 8 Fields by 0 Rows -// +----------------+----------------+----------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// | Name: kind | Name: uid | Name: name | Name: panel_type | Name: url | Name: tags | Name: ds_uid | Name: location | -// | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | -// | Type: []string | Type: []string | Type: []string | Type: []string | Type: []string | Type: []*json.RawMessage | Type: []json.RawMessage | Type: []string | -// +----------------+----------------+----------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// +----------------+----------------+----------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// -// -// 🌟 This was machine generated. Do not edit. 🌟 -{ - "status": 200, - "frames": [ - { - "schema": { - "name": "Query results", - "meta": { - "type": "search-results", - "typeVersion": [ - 0, - 0 - ], - "custom": { - "count": 0 - } - }, - "fields": [ - { - "name": "kind", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "uid", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "name", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "panel_type", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "url", - "type": "string", - "typeInfo": { - "frame": "string" - }, - "config": { - "links": [ - { - "title": "link", - "url": "${__value.text}" - } - ] - } - }, - { - "name": "tags", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage", - "nullable": true - } - }, - { - "name": "ds_uid", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage" - } - }, - { - "name": "location", - "type": "string", - "typeInfo": { - "frame": "string" - } - } - ] - }, - "data": { - "values": [ - [], - [], - [], - [], - [], - [], - [], - [] - ] - } - } - ] -} \ No newline at end of file diff --git a/pkg/services/searchV2/testdata/basic-search.jsonc b/pkg/services/searchV2/testdata/basic-search.jsonc deleted file mode 100644 index 357cbd3932a..00000000000 --- a/pkg/services/searchV2/testdata/basic-search.jsonc +++ /dev/null @@ -1,139 +0,0 @@ -// 🌟 This was machine generated. Do not edit. 🌟 -// -// Frame[0] { -// "type": "search-results", -// "typeVersion": [ -// 0, -// 0 -// ], -// "custom": { -// "count": 1 -// } -// } -// Name: Query results -// Dimensions: 8 Fields by 1 Rows -// +----------------+----------------+----------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// | Name: kind | Name: uid | Name: name | Name: panel_type | Name: url | Name: tags | Name: ds_uid | Name: location | -// | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | -// | Type: []string | Type: []string | Type: []string | Type: []string | Type: []string | Type: []*json.RawMessage | Type: []json.RawMessage | Type: []string | -// +----------------+----------------+----------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// | dashboard | 2 | boom | | /pfix/d/2/ | null | [] | general | -// +----------------+----------------+----------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// -// -// 🌟 This was machine generated. Do not edit. 🌟 -{ - "status": 200, - "frames": [ - { - "schema": { - "name": "Query results", - "meta": { - "type": "search-results", - "typeVersion": [ - 0, - 0 - ], - "custom": { - "count": 1 - } - }, - "fields": [ - { - "name": "kind", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "uid", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "name", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "panel_type", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "url", - "type": "string", - "typeInfo": { - "frame": "string" - }, - "config": { - "links": [ - { - "title": "link", - "url": "${__value.text}" - } - ] - } - }, - { - "name": "tags", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage", - "nullable": true - } - }, - { - "name": "ds_uid", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage" - } - }, - { - "name": "location", - "type": "string", - "typeInfo": { - "frame": "string" - } - } - ] - }, - "data": { - "values": [ - [ - "dashboard" - ], - [ - "2" - ], - [ - "boom" - ], - [ - "" - ], - [ - "/pfix/d/2/" - ], - [ - null - ], - [ - [] - ], - [ - "general" - ] - ] - } - } - ] -} \ No newline at end of file diff --git a/pkg/services/searchV2/testdata/dashboard-create.jsonc b/pkg/services/searchV2/testdata/dashboard-create.jsonc deleted file mode 100644 index de942bd9df5..00000000000 --- a/pkg/services/searchV2/testdata/dashboard-create.jsonc +++ /dev/null @@ -1,139 +0,0 @@ -// 🌟 This was machine generated. Do not edit. 🌟 -// -// Frame[0] { -// "type": "search-results", -// "typeVersion": [ -// 0, -// 0 -// ], -// "custom": { -// "count": 1 -// } -// } -// Name: Query results -// Dimensions: 8 Fields by 1 Rows -// +----------------+----------------+----------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// | Name: kind | Name: uid | Name: name | Name: panel_type | Name: url | Name: tags | Name: ds_uid | Name: location | -// | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | -// | Type: []string | Type: []string | Type: []string | Type: []string | Type: []string | Type: []*json.RawMessage | Type: []json.RawMessage | Type: []string | -// +----------------+----------------+----------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// | dashboard | 3 | created | | /pfix/d/3/ | null | [] | general | -// +----------------+----------------+----------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// -// -// 🌟 This was machine generated. Do not edit. 🌟 -{ - "status": 200, - "frames": [ - { - "schema": { - "name": "Query results", - "meta": { - "type": "search-results", - "typeVersion": [ - 0, - 0 - ], - "custom": { - "count": 1 - } - }, - "fields": [ - { - "name": "kind", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "uid", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "name", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "panel_type", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "url", - "type": "string", - "typeInfo": { - "frame": "string" - }, - "config": { - "links": [ - { - "title": "link", - "url": "${__value.text}" - } - ] - } - }, - { - "name": "tags", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage", - "nullable": true - } - }, - { - "name": "ds_uid", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage" - } - }, - { - "name": "location", - "type": "string", - "typeInfo": { - "frame": "string" - } - } - ] - }, - "data": { - "values": [ - [ - "dashboard" - ], - [ - "3" - ], - [ - "created" - ], - [ - "" - ], - [ - "/pfix/d/3/" - ], - [ - null - ], - [ - [] - ], - [ - "general" - ] - ] - } - } - ] -} \ No newline at end of file diff --git a/pkg/services/searchV2/testdata/dashboard-delete.jsonc b/pkg/services/searchV2/testdata/dashboard-delete.jsonc deleted file mode 100644 index a5e0a619ad3..00000000000 --- a/pkg/services/searchV2/testdata/dashboard-delete.jsonc +++ /dev/null @@ -1,122 +0,0 @@ -// 🌟 This was machine generated. Do not edit. 🌟 -// -// Frame[0] { -// "type": "search-results", -// "typeVersion": [ -// 0, -// 0 -// ], -// "custom": { -// "count": 0 -// } -// } -// Name: Query results -// Dimensions: 8 Fields by 0 Rows -// +----------------+----------------+----------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// | Name: kind | Name: uid | Name: name | Name: panel_type | Name: url | Name: tags | Name: ds_uid | Name: location | -// | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | -// | Type: []string | Type: []string | Type: []string | Type: []string | Type: []string | Type: []*json.RawMessage | Type: []json.RawMessage | Type: []string | -// +----------------+----------------+----------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// +----------------+----------------+----------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// -// -// 🌟 This was machine generated. Do not edit. 🌟 -{ - "status": 200, - "frames": [ - { - "schema": { - "name": "Query results", - "meta": { - "type": "search-results", - "typeVersion": [ - 0, - 0 - ], - "custom": { - "count": 0 - } - }, - "fields": [ - { - "name": "kind", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "uid", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "name", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "panel_type", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "url", - "type": "string", - "typeInfo": { - "frame": "string" - }, - "config": { - "links": [ - { - "title": "link", - "url": "${__value.text}" - } - ] - } - }, - { - "name": "tags", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage", - "nullable": true - } - }, - { - "name": "ds_uid", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage" - } - }, - { - "name": "location", - "type": "string", - "typeInfo": { - "frame": "string" - } - } - ] - }, - "data": { - "values": [ - [], - [], - [], - [], - [], - [], - [], - [] - ] - } - } - ] -} \ No newline at end of file diff --git a/pkg/services/searchV2/testdata/dashboard-update.jsonc b/pkg/services/searchV2/testdata/dashboard-update.jsonc deleted file mode 100644 index 0b92ff27ff8..00000000000 --- a/pkg/services/searchV2/testdata/dashboard-update.jsonc +++ /dev/null @@ -1,139 +0,0 @@ -// 🌟 This was machine generated. Do not edit. 🌟 -// -// Frame[0] { -// "type": "search-results", -// "typeVersion": [ -// 0, -// 0 -// ], -// "custom": { -// "count": 1 -// } -// } -// Name: Query results -// Dimensions: 8 Fields by 1 Rows -// +----------------+----------------+----------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// | Name: kind | Name: uid | Name: name | Name: panel_type | Name: url | Name: tags | Name: ds_uid | Name: location | -// | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | -// | Type: []string | Type: []string | Type: []string | Type: []string | Type: []string | Type: []*json.RawMessage | Type: []json.RawMessage | Type: []string | -// +----------------+----------------+----------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// | dashboard | 2 | nginx | | /pfix/d/2/ | null | [] | general | -// +----------------+----------------+----------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// -// -// 🌟 This was machine generated. Do not edit. 🌟 -{ - "status": 200, - "frames": [ - { - "schema": { - "name": "Query results", - "meta": { - "type": "search-results", - "typeVersion": [ - 0, - 0 - ], - "custom": { - "count": 1 - } - }, - "fields": [ - { - "name": "kind", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "uid", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "name", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "panel_type", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "url", - "type": "string", - "typeInfo": { - "frame": "string" - }, - "config": { - "links": [ - { - "title": "link", - "url": "${__value.text}" - } - ] - } - }, - { - "name": "tags", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage", - "nullable": true - } - }, - { - "name": "ds_uid", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage" - } - }, - { - "name": "location", - "type": "string", - "typeInfo": { - "frame": "string" - } - } - ] - }, - "data": { - "values": [ - [ - "dashboard" - ], - [ - "2" - ], - [ - "nginx" - ], - [ - "" - ], - [ - "/pfix/d/2/" - ], - [ - null - ], - [ - [] - ], - [ - "general" - ] - ] - } - } - ] -} \ No newline at end of file diff --git a/pkg/services/searchV2/testdata/folders-dashboard-removed-on-folder-removed.jsonc b/pkg/services/searchV2/testdata/folders-dashboard-removed-on-folder-removed.jsonc deleted file mode 100644 index 36b99ff6c19..00000000000 --- a/pkg/services/searchV2/testdata/folders-dashboard-removed-on-folder-removed.jsonc +++ /dev/null @@ -1,139 +0,0 @@ -// 🌟 This was machine generated. Do not edit. 🌟 -// -// Frame[0] { -// "type": "search-results", -// "typeVersion": [ -// 0, -// 0 -// ], -// "custom": { -// "count": 1 -// } -// } -// Name: Query results -// Dimensions: 8 Fields by 1 Rows -// +----------------+----------------+----------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// | Name: kind | Name: uid | Name: name | Name: panel_type | Name: url | Name: tags | Name: ds_uid | Name: location | -// | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | -// | Type: []string | Type: []string | Type: []string | Type: []string | Type: []string | Type: []*json.RawMessage | Type: []json.RawMessage | Type: []string | -// +----------------+----------------+----------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// | dashboard | 4 | One more dash | | /pfix/d/4/ | null | [] | general | -// +----------------+----------------+----------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// -// -// 🌟 This was machine generated. Do not edit. 🌟 -{ - "status": 200, - "frames": [ - { - "schema": { - "name": "Query results", - "meta": { - "type": "search-results", - "typeVersion": [ - 0, - 0 - ], - "custom": { - "count": 1 - } - }, - "fields": [ - { - "name": "kind", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "uid", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "name", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "panel_type", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "url", - "type": "string", - "typeInfo": { - "frame": "string" - }, - "config": { - "links": [ - { - "title": "link", - "url": "${__value.text}" - } - ] - } - }, - { - "name": "tags", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage", - "nullable": true - } - }, - { - "name": "ds_uid", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage" - } - }, - { - "name": "location", - "type": "string", - "typeInfo": { - "frame": "string" - } - } - ] - }, - "data": { - "values": [ - [ - "dashboard" - ], - [ - "4" - ], - [ - "One more dash" - ], - [ - "" - ], - [ - "/pfix/d/4/" - ], - [ - null - ], - [ - [] - ], - [ - "general" - ] - ] - } - } - ] -} \ No newline at end of file diff --git a/pkg/services/searchV2/testdata/folders-indexed.jsonc b/pkg/services/searchV2/testdata/folders-indexed.jsonc deleted file mode 100644 index 000926486eb..00000000000 --- a/pkg/services/searchV2/testdata/folders-indexed.jsonc +++ /dev/null @@ -1,139 +0,0 @@ -// 🌟 This was machine generated. Do not edit. 🌟 -// -// Frame[0] { -// "type": "search-results", -// "typeVersion": [ -// 0, -// 0 -// ], -// "custom": { -// "count": 1 -// } -// } -// Name: Query results -// Dimensions: 8 Fields by 1 Rows -// +----------------+----------------+----------------+------------------+-----------------------+--------------------------+-------------------------+----------------+ -// | Name: kind | Name: uid | Name: name | Name: panel_type | Name: url | Name: tags | Name: ds_uid | Name: location | -// | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | -// | Type: []string | Type: []string | Type: []string | Type: []string | Type: []string | Type: []*json.RawMessage | Type: []json.RawMessage | Type: []string | -// +----------------+----------------+----------------+------------------+-----------------------+--------------------------+-------------------------+----------------+ -// | folder | 1 | My folder | | /pfix/dashboards/f/1/ | null | [] | | -// +----------------+----------------+----------------+------------------+-----------------------+--------------------------+-------------------------+----------------+ -// -// -// 🌟 This was machine generated. Do not edit. 🌟 -{ - "status": 200, - "frames": [ - { - "schema": { - "name": "Query results", - "meta": { - "type": "search-results", - "typeVersion": [ - 0, - 0 - ], - "custom": { - "count": 1 - } - }, - "fields": [ - { - "name": "kind", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "uid", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "name", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "panel_type", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "url", - "type": "string", - "typeInfo": { - "frame": "string" - }, - "config": { - "links": [ - { - "title": "link", - "url": "${__value.text}" - } - ] - } - }, - { - "name": "tags", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage", - "nullable": true - } - }, - { - "name": "ds_uid", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage" - } - }, - { - "name": "location", - "type": "string", - "typeInfo": { - "frame": "string" - } - } - ] - }, - "data": { - "values": [ - [ - "folder" - ], - [ - "1" - ], - [ - "My folder" - ], - [ - "" - ], - [ - "/pfix/dashboards/f/1/" - ], - [ - null - ], - [ - [] - ], - [ - "" - ] - ] - } - } - ] -} \ No newline at end of file diff --git a/pkg/services/searchV2/testdata/multiple-tokens-beginning-lower.jsonc b/pkg/services/searchV2/testdata/multiple-tokens-beginning-lower.jsonc deleted file mode 100644 index 540543f0a1e..00000000000 --- a/pkg/services/searchV2/testdata/multiple-tokens-beginning-lower.jsonc +++ /dev/null @@ -1,139 +0,0 @@ -// 🌟 This was machine generated. Do not edit. 🌟 -// -// Frame[0] { -// "type": "search-results", -// "typeVersion": [ -// 0, -// 0 -// ], -// "custom": { -// "count": 1 -// } -// } -// Name: Query results -// Dimensions: 8 Fields by 1 Rows -// +----------------+----------------+--------------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// | Name: kind | Name: uid | Name: name | Name: panel_type | Name: url | Name: tags | Name: ds_uid | Name: location | -// | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | -// | Type: []string | Type: []string | Type: []string | Type: []string | Type: []string | Type: []*json.RawMessage | Type: []json.RawMessage | Type: []string | -// +----------------+----------------+--------------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// | dashboard | 1 | Archer Data System | | /pfix/d/1/ | null | [] | general | -// +----------------+----------------+--------------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// -// -// 🌟 This was machine generated. Do not edit. 🌟 -{ - "status": 200, - "frames": [ - { - "schema": { - "name": "Query results", - "meta": { - "type": "search-results", - "typeVersion": [ - 0, - 0 - ], - "custom": { - "count": 1 - } - }, - "fields": [ - { - "name": "kind", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "uid", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "name", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "panel_type", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "url", - "type": "string", - "typeInfo": { - "frame": "string" - }, - "config": { - "links": [ - { - "title": "link", - "url": "${__value.text}" - } - ] - } - }, - { - "name": "tags", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage", - "nullable": true - } - }, - { - "name": "ds_uid", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage" - } - }, - { - "name": "location", - "type": "string", - "typeInfo": { - "frame": "string" - } - } - ] - }, - "data": { - "values": [ - [ - "dashboard" - ], - [ - "1" - ], - [ - "Archer Data System" - ], - [ - "" - ], - [ - "/pfix/d/1/" - ], - [ - null - ], - [ - [] - ], - [ - "general" - ] - ] - } - } - ] -} \ No newline at end of file diff --git a/pkg/services/searchV2/testdata/multiple-tokens-beginning.jsonc b/pkg/services/searchV2/testdata/multiple-tokens-beginning.jsonc deleted file mode 100644 index 540543f0a1e..00000000000 --- a/pkg/services/searchV2/testdata/multiple-tokens-beginning.jsonc +++ /dev/null @@ -1,139 +0,0 @@ -// 🌟 This was machine generated. Do not edit. 🌟 -// -// Frame[0] { -// "type": "search-results", -// "typeVersion": [ -// 0, -// 0 -// ], -// "custom": { -// "count": 1 -// } -// } -// Name: Query results -// Dimensions: 8 Fields by 1 Rows -// +----------------+----------------+--------------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// | Name: kind | Name: uid | Name: name | Name: panel_type | Name: url | Name: tags | Name: ds_uid | Name: location | -// | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | -// | Type: []string | Type: []string | Type: []string | Type: []string | Type: []string | Type: []*json.RawMessage | Type: []json.RawMessage | Type: []string | -// +----------------+----------------+--------------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// | dashboard | 1 | Archer Data System | | /pfix/d/1/ | null | [] | general | -// +----------------+----------------+--------------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// -// -// 🌟 This was machine generated. Do not edit. 🌟 -{ - "status": 200, - "frames": [ - { - "schema": { - "name": "Query results", - "meta": { - "type": "search-results", - "typeVersion": [ - 0, - 0 - ], - "custom": { - "count": 1 - } - }, - "fields": [ - { - "name": "kind", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "uid", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "name", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "panel_type", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "url", - "type": "string", - "typeInfo": { - "frame": "string" - }, - "config": { - "links": [ - { - "title": "link", - "url": "${__value.text}" - } - ] - } - }, - { - "name": "tags", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage", - "nullable": true - } - }, - { - "name": "ds_uid", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage" - } - }, - { - "name": "location", - "type": "string", - "typeInfo": { - "frame": "string" - } - } - ] - }, - "data": { - "values": [ - [ - "dashboard" - ], - [ - "1" - ], - [ - "Archer Data System" - ], - [ - "" - ], - [ - "/pfix/d/1/" - ], - [ - null - ], - [ - [] - ], - [ - "general" - ] - ] - } - } - ] -} \ No newline at end of file diff --git a/pkg/services/searchV2/testdata/multiple-tokens-middle-lower.jsonc b/pkg/services/searchV2/testdata/multiple-tokens-middle-lower.jsonc deleted file mode 100644 index 1bcf58aa7f7..00000000000 --- a/pkg/services/searchV2/testdata/multiple-tokens-middle-lower.jsonc +++ /dev/null @@ -1,139 +0,0 @@ -// 🌟 This was machine generated. Do not edit. 🌟 -// -// Frame[0] { -// "type": "search-results", -// "typeVersion": [ -// 0, -// 0 -// ], -// "custom": { -// "count": 1 -// } -// } -// Name: Query results -// Dimensions: 8 Fields by 1 Rows -// +----------------+----------------+--------------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// | Name: kind | Name: uid | Name: name | Name: panel_type | Name: url | Name: tags | Name: ds_uid | Name: location | -// | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | -// | Type: []string | Type: []string | Type: []string | Type: []string | Type: []string | Type: []*json.RawMessage | Type: []json.RawMessage | Type: []string | -// +----------------+----------------+--------------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// | dashboard | 2 | Document Sync repo | | /pfix/d/2/ | null | [] | general | -// +----------------+----------------+--------------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// -// -// 🌟 This was machine generated. Do not edit. 🌟 -{ - "status": 200, - "frames": [ - { - "schema": { - "name": "Query results", - "meta": { - "type": "search-results", - "typeVersion": [ - 0, - 0 - ], - "custom": { - "count": 1 - } - }, - "fields": [ - { - "name": "kind", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "uid", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "name", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "panel_type", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "url", - "type": "string", - "typeInfo": { - "frame": "string" - }, - "config": { - "links": [ - { - "title": "link", - "url": "${__value.text}" - } - ] - } - }, - { - "name": "tags", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage", - "nullable": true - } - }, - { - "name": "ds_uid", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage" - } - }, - { - "name": "location", - "type": "string", - "typeInfo": { - "frame": "string" - } - } - ] - }, - "data": { - "values": [ - [ - "dashboard" - ], - [ - "2" - ], - [ - "Document Sync repo" - ], - [ - "" - ], - [ - "/pfix/d/2/" - ], - [ - null - ], - [ - [] - ], - [ - "general" - ] - ] - } - } - ] -} \ No newline at end of file diff --git a/pkg/services/searchV2/testdata/multiple-tokens-middle.jsonc b/pkg/services/searchV2/testdata/multiple-tokens-middle.jsonc deleted file mode 100644 index 540543f0a1e..00000000000 --- a/pkg/services/searchV2/testdata/multiple-tokens-middle.jsonc +++ /dev/null @@ -1,139 +0,0 @@ -// 🌟 This was machine generated. Do not edit. 🌟 -// -// Frame[0] { -// "type": "search-results", -// "typeVersion": [ -// 0, -// 0 -// ], -// "custom": { -// "count": 1 -// } -// } -// Name: Query results -// Dimensions: 8 Fields by 1 Rows -// +----------------+----------------+--------------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// | Name: kind | Name: uid | Name: name | Name: panel_type | Name: url | Name: tags | Name: ds_uid | Name: location | -// | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | -// | Type: []string | Type: []string | Type: []string | Type: []string | Type: []string | Type: []*json.RawMessage | Type: []json.RawMessage | Type: []string | -// +----------------+----------------+--------------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// | dashboard | 1 | Archer Data System | | /pfix/d/1/ | null | [] | general | -// +----------------+----------------+--------------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// -// -// 🌟 This was machine generated. Do not edit. 🌟 -{ - "status": 200, - "frames": [ - { - "schema": { - "name": "Query results", - "meta": { - "type": "search-results", - "typeVersion": [ - 0, - 0 - ], - "custom": { - "count": 1 - } - }, - "fields": [ - { - "name": "kind", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "uid", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "name", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "panel_type", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "url", - "type": "string", - "typeInfo": { - "frame": "string" - }, - "config": { - "links": [ - { - "title": "link", - "url": "${__value.text}" - } - ] - } - }, - { - "name": "tags", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage", - "nullable": true - } - }, - { - "name": "ds_uid", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage" - } - }, - { - "name": "location", - "type": "string", - "typeInfo": { - "frame": "string" - } - } - ] - }, - "data": { - "values": [ - [ - "dashboard" - ], - [ - "1" - ], - [ - "Archer Data System" - ], - [ - "" - ], - [ - "/pfix/d/1/" - ], - [ - null - ], - [ - [] - ], - [ - "general" - ] - ] - } - } - ] -} \ No newline at end of file diff --git a/pkg/services/searchV2/testdata/ngram-camel-case-split.jsonc b/pkg/services/searchV2/testdata/ngram-camel-case-split.jsonc deleted file mode 100644 index d26f38f5121..00000000000 --- a/pkg/services/searchV2/testdata/ngram-camel-case-split.jsonc +++ /dev/null @@ -1,139 +0,0 @@ -// 🌟 This was machine generated. Do not edit. 🌟 -// -// Frame[0] { -// "type": "search-results", -// "typeVersion": [ -// 0, -// 0 -// ], -// "custom": { -// "count": 1 -// } -// } -// Name: Query results -// Dimensions: 8 Fields by 1 Rows -// +----------------+----------------+----------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// | Name: kind | Name: uid | Name: name | Name: panel_type | Name: url | Name: tags | Name: ds_uid | Name: location | -// | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | -// | Type: []string | Type: []string | Type: []string | Type: []string | Type: []string | Type: []*json.RawMessage | Type: []json.RawMessage | Type: []string | -// +----------------+----------------+----------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// | dashboard | 1 | heatTorkel | | /pfix/d/1/ | null | [] | general | -// +----------------+----------------+----------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// -// -// 🌟 This was machine generated. Do not edit. 🌟 -{ - "status": 200, - "frames": [ - { - "schema": { - "name": "Query results", - "meta": { - "type": "search-results", - "typeVersion": [ - 0, - 0 - ], - "custom": { - "count": 1 - } - }, - "fields": [ - { - "name": "kind", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "uid", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "name", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "panel_type", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "url", - "type": "string", - "typeInfo": { - "frame": "string" - }, - "config": { - "links": [ - { - "title": "link", - "url": "${__value.text}" - } - ] - } - }, - { - "name": "tags", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage", - "nullable": true - } - }, - { - "name": "ds_uid", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage" - } - }, - { - "name": "location", - "type": "string", - "typeInfo": { - "frame": "string" - } - } - ] - }, - "data": { - "values": [ - [ - "dashboard" - ], - [ - "1" - ], - [ - "heatTorkel" - ], - [ - "" - ], - [ - "/pfix/d/1/" - ], - [ - null - ], - [ - [] - ], - [ - "general" - ] - ] - } - } - ] -} \ No newline at end of file diff --git a/pkg/services/searchV2/testdata/ngram-punctuation-split.jsonc b/pkg/services/searchV2/testdata/ngram-punctuation-split.jsonc deleted file mode 100644 index 46e9db22ca1..00000000000 --- a/pkg/services/searchV2/testdata/ngram-punctuation-split.jsonc +++ /dev/null @@ -1,139 +0,0 @@ -// 🌟 This was machine generated. Do not edit. 🌟 -// -// Frame[0] { -// "type": "search-results", -// "typeVersion": [ -// 0, -// 0 -// ], -// "custom": { -// "count": 1 -// } -// } -// Name: Query results -// Dimensions: 8 Fields by 1 Rows -// +----------------+----------------+----------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// | Name: kind | Name: uid | Name: name | Name: panel_type | Name: url | Name: tags | Name: ds_uid | Name: location | -// | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | -// | Type: []string | Type: []string | Type: []string | Type: []string | Type: []string | Type: []*json.RawMessage | Type: []json.RawMessage | Type: []string | -// +----------------+----------------+----------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// | dashboard | 1 | heat-torkel | | /pfix/d/1/ | null | [] | general | -// +----------------+----------------+----------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// -// -// 🌟 This was machine generated. Do not edit. 🌟 -{ - "status": 200, - "frames": [ - { - "schema": { - "name": "Query results", - "meta": { - "type": "search-results", - "typeVersion": [ - 0, - 0 - ], - "custom": { - "count": 1 - } - }, - "fields": [ - { - "name": "kind", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "uid", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "name", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "panel_type", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "url", - "type": "string", - "typeInfo": { - "frame": "string" - }, - "config": { - "links": [ - { - "title": "link", - "url": "${__value.text}" - } - ] - } - }, - { - "name": "tags", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage", - "nullable": true - } - }, - { - "name": "ds_uid", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage" - } - }, - { - "name": "location", - "type": "string", - "typeInfo": { - "frame": "string" - } - } - ] - }, - "data": { - "values": [ - [ - "dashboard" - ], - [ - "1" - ], - [ - "heat-torkel" - ], - [ - "" - ], - [ - "/pfix/d/1/" - ], - [ - null - ], - [ - [] - ], - [ - "general" - ] - ] - } - } - ] -} \ No newline at end of file diff --git a/pkg/services/searchV2/testdata/ngram-simple.jsonc b/pkg/services/searchV2/testdata/ngram-simple.jsonc deleted file mode 100644 index d3d1875f619..00000000000 --- a/pkg/services/searchV2/testdata/ngram-simple.jsonc +++ /dev/null @@ -1,148 +0,0 @@ -// 🌟 This was machine generated. Do not edit. 🌟 -// -// Frame[0] { -// "type": "search-results", -// "typeVersion": [ -// 0, -// 0 -// ], -// "custom": { -// "count": 2 -// } -// } -// Name: Query results -// Dimensions: 8 Fields by 2 Rows -// +----------------+----------------+------------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// | Name: kind | Name: uid | Name: name | Name: panel_type | Name: url | Name: tags | Name: ds_uid | Name: location | -// | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | -// | Type: []string | Type: []string | Type: []string | Type: []string | Type: []string | Type: []*json.RawMessage | Type: []json.RawMessage | Type: []string | -// +----------------+----------------+------------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// | dashboard | 1 | heat-torkel | | /pfix/d/1/ | null | [] | general | -// | dashboard | 2 | topology heatmap | | /pfix/d/2/ | null | [] | general | -// +----------------+----------------+------------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// -// -// 🌟 This was machine generated. Do not edit. 🌟 -{ - "status": 200, - "frames": [ - { - "schema": { - "name": "Query results", - "meta": { - "type": "search-results", - "typeVersion": [ - 0, - 0 - ], - "custom": { - "count": 2 - } - }, - "fields": [ - { - "name": "kind", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "uid", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "name", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "panel_type", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "url", - "type": "string", - "typeInfo": { - "frame": "string" - }, - "config": { - "links": [ - { - "title": "link", - "url": "${__value.text}" - } - ] - } - }, - { - "name": "tags", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage", - "nullable": true - } - }, - { - "name": "ds_uid", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage" - } - }, - { - "name": "location", - "type": "string", - "typeInfo": { - "frame": "string" - } - } - ] - }, - "data": { - "values": [ - [ - "dashboard", - "dashboard" - ], - [ - "1", - "2" - ], - [ - "heat-torkel", - "topology heatmap" - ], - [ - "", - "" - ], - [ - "/pfix/d/1/", - "/pfix/d/2/" - ], - [ - null, - null - ], - [ - [], - [] - ], - [ - "general", - "general" - ] - ] - } - } - ] -} \ No newline at end of file diff --git a/pkg/services/searchV2/testdata/ordering-tests-1-[Prometheus_2.].jsonc b/pkg/services/searchV2/testdata/ordering-tests-1-[Prometheus_2.].jsonc deleted file mode 100644 index 9db5c2c7711..00000000000 --- a/pkg/services/searchV2/testdata/ordering-tests-1-[Prometheus_2.].jsonc +++ /dev/null @@ -1,54 +0,0 @@ -// 🌟 This was machine generated. Do not edit. 🌟 -// -// Frame[0] -// Name: ordering frame -// Dimensions: 2 Fields by 2 Rows -// +----------------------+-------------------+ -// | Name: name | Name: score | -// | Labels: | Labels: | -// | Type: []string | Type: []float64 | -// +----------------------+-------------------+ -// | Prometheus 2.0 | 7.621131552585596 | -// | Prometheus 2.0 Stats | 7.621131552585596 | -// +----------------------+-------------------+ -// -// -// 🌟 This was machine generated. Do not edit. 🌟 -{ - "status": 200, - "frames": [ - { - "schema": { - "name": "ordering frame", - "fields": [ - { - "name": "name", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "score", - "type": "number", - "typeInfo": { - "frame": "float64" - } - } - ] - }, - "data": { - "values": [ - [ - "Prometheus 2.0", - "Prometheus 2.0 Stats" - ], - [ - 7.621131552585596, - 7.621131552585596 - ] - ] - } - } - ] -} \ No newline at end of file diff --git a/pkg/services/searchV2/testdata/ordering-tests-2-[Prome].jsonc b/pkg/services/searchV2/testdata/ordering-tests-2-[Prome].jsonc deleted file mode 100644 index 4e8c4f8906e..00000000000 --- a/pkg/services/searchV2/testdata/ordering-tests-2-[Prome].jsonc +++ /dev/null @@ -1,60 +0,0 @@ -// 🌟 This was machine generated. Do not edit. 🌟 -// -// Frame[0] -// Name: ordering frame -// Dimensions: 2 Fields by 4 Rows -// +----------------------+-------------------+ -// | Name: name | Name: score | -// | Labels: | Labels: | -// | Type: []string | Type: []float64 | -// +----------------------+-------------------+ -// | Prometheus 2.0 | 9.502378631081775 | -// | Prometheus 20.0 | 9.458475876581684 | -// | Prometheus Stats | 9.379374926302209 | -// | Prometheus 2.0 Stats | 9.310081326315688 | -// +----------------------+-------------------+ -// -// -// 🌟 This was machine generated. Do not edit. 🌟 -{ - "status": 200, - "frames": [ - { - "schema": { - "name": "ordering frame", - "fields": [ - { - "name": "name", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "score", - "type": "number", - "typeInfo": { - "frame": "float64" - } - } - ] - }, - "data": { - "values": [ - [ - "Prometheus 2.0", - "Prometheus 20.0", - "Prometheus Stats", - "Prometheus 2.0 Stats" - ], - [ - 9.502378631081775, - 9.458475876581684, - 9.379374926302209, - 9.310081326315688 - ] - ] - } - } - ] -} \ No newline at end of file diff --git a/pkg/services/searchV2/testdata/ordering-tests-3-[Prometheus_stat].jsonc b/pkg/services/searchV2/testdata/ordering-tests-3-[Prometheus_stat].jsonc deleted file mode 100644 index 64ee875a6ac..00000000000 --- a/pkg/services/searchV2/testdata/ordering-tests-3-[Prometheus_stat].jsonc +++ /dev/null @@ -1,51 +0,0 @@ -// 🌟 This was machine generated. Do not edit. 🌟 -// -// Frame[0] -// Name: ordering frame -// Dimensions: 2 Fields by 1 Rows -// +------------------+-------------------+ -// | Name: name | Name: score | -// | Labels: | Labels: | -// | Type: []string | Type: []float64 | -// +------------------+-------------------+ -// | Prometheus Stats | 7.621131552585596 | -// +------------------+-------------------+ -// -// -// 🌟 This was machine generated. Do not edit. 🌟 -{ - "status": 200, - "frames": [ - { - "schema": { - "name": "ordering frame", - "fields": [ - { - "name": "name", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "score", - "type": "number", - "typeInfo": { - "frame": "float64" - } - } - ] - }, - "data": { - "values": [ - [ - "Prometheus Stats" - ], - [ - 7.621131552585596 - ] - ] - } - } - ] -} \ No newline at end of file diff --git a/pkg/services/searchV2/testdata/ordering-tests-4-[Loki_2.].jsonc b/pkg/services/searchV2/testdata/ordering-tests-4-[Loki_2.].jsonc deleted file mode 100644 index ada668cc3a9..00000000000 --- a/pkg/services/searchV2/testdata/ordering-tests-4-[Loki_2.].jsonc +++ /dev/null @@ -1,63 +0,0 @@ -// 🌟 This was machine generated. Do not edit. 🌟 -// -// Frame[0] -// Name: ordering frame -// Dimensions: 2 Fields by 5 Rows -// +--------------------------+--------------------+ -// | Name: name | Name: score | -// | Labels: | Labels: | -// | Type: []string | Type: []float64 | -// +--------------------------+--------------------+ -// | Loki 2.0 | 9.273036652923247 | -// | Loki 2.0 Stats | 8.951742733604135 | -// | Loki 20.0 | 2.57580523764178 | -// | Loki histogram2 | 2.2807887502617943 | -// | Loki Tests - Bar Gauge 2 | 2.045832444623899 | -// +--------------------------+--------------------+ -// -// -// 🌟 This was machine generated. Do not edit. 🌟 -{ - "status": 200, - "frames": [ - { - "schema": { - "name": "ordering frame", - "fields": [ - { - "name": "name", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "score", - "type": "number", - "typeInfo": { - "frame": "float64" - } - } - ] - }, - "data": { - "values": [ - [ - "Loki 2.0", - "Loki 2.0 Stats", - "Loki 20.0", - "Loki histogram2", - "Loki Tests - Bar Gauge 2" - ], - [ - 9.273036652923247, - 8.951742733604135, - 2.57580523764178, - 2.2807887502617943, - 2.045832444623899 - ] - ] - } - } - ] -} \ No newline at end of file diff --git a/pkg/services/searchV2/testdata/ordering-tests-5-[Lok].jsonc b/pkg/services/searchV2/testdata/ordering-tests-5-[Lok].jsonc deleted file mode 100644 index 9b5bf376723..00000000000 --- a/pkg/services/searchV2/testdata/ordering-tests-5-[Lok].jsonc +++ /dev/null @@ -1,72 +0,0 @@ -// 🌟 This was machine generated. Do not edit. 🌟 -// -// Frame[0] -// Name: ordering frame -// Dimensions: 2 Fields by 8 Rows -// +--------------------------+-------------------+ -// | Name: name | Name: score | -// | Labels: | Labels: | -// | Type: []string | Type: []float64 | -// +--------------------------+-------------------+ -// | Loki 2.0 | 8.386497572003142 | -// | Loki 20.0 | 8.351238737232393 | -// | Loki Stats | 8.289644692681875 | -// | Loki 2.0 Stats | 8.237634633059454 | -// | Loki histogram | 8.237634633059454 | -// | Loki histogram2 | 8.214550743132483 | -// | Loki Second Word | 8.173207674966303 | -// | Loki Tests - Bar Gauge 2 | 8.105690026892566 | -// +--------------------------+-------------------+ -// -// -// 🌟 This was machine generated. Do not edit. 🌟 -{ - "status": 200, - "frames": [ - { - "schema": { - "name": "ordering frame", - "fields": [ - { - "name": "name", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "score", - "type": "number", - "typeInfo": { - "frame": "float64" - } - } - ] - }, - "data": { - "values": [ - [ - "Loki 2.0", - "Loki 20.0", - "Loki Stats", - "Loki 2.0 Stats", - "Loki histogram", - "Loki histogram2", - "Loki Second Word", - "Loki Tests - Bar Gauge 2" - ], - [ - 8.386497572003142, - 8.351238737232393, - 8.289644692681875, - 8.237634633059454, - 8.237634633059454, - 8.214550743132483, - 8.173207674966303, - 8.105690026892566 - ] - ] - } - } - ] -} \ No newline at end of file diff --git a/pkg/services/searchV2/testdata/ordering-tests-6-[Loki_stats].jsonc b/pkg/services/searchV2/testdata/ordering-tests-6-[Loki_stats].jsonc deleted file mode 100644 index 1f89f04c7f0..00000000000 --- a/pkg/services/searchV2/testdata/ordering-tests-6-[Loki_stats].jsonc +++ /dev/null @@ -1,54 +0,0 @@ -// 🌟 This was machine generated. Do not edit. 🌟 -// -// Frame[0] -// Name: ordering frame -// Dimensions: 2 Fields by 2 Rows -// +----------------+-------------------+ -// | Name: name | Name: score | -// | Labels: | Labels: | -// | Type: []string | Type: []float64 | -// +----------------+-------------------+ -// | Loki Stats | 9.397899591158676 | -// | Loki 2.0 Stats | 2.638536183312778 | -// +----------------+-------------------+ -// -// -// 🌟 This was machine generated. Do not edit. 🌟 -{ - "status": 200, - "frames": [ - { - "schema": { - "name": "ordering frame", - "fields": [ - { - "name": "name", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "score", - "type": "number", - "typeInfo": { - "frame": "float64" - } - } - ] - }, - "data": { - "values": [ - [ - "Loki Stats", - "Loki 2.0 Stats" - ], - [ - 9.397899591158676, - 2.638536183312778 - ] - ] - } - } - ] -} \ No newline at end of file diff --git a/pkg/services/searchV2/testdata/panels-panel-removed-on-dashboard-removed.jsonc b/pkg/services/searchV2/testdata/panels-panel-removed-on-dashboard-removed.jsonc deleted file mode 100644 index a5e0a619ad3..00000000000 --- a/pkg/services/searchV2/testdata/panels-panel-removed-on-dashboard-removed.jsonc +++ /dev/null @@ -1,122 +0,0 @@ -// 🌟 This was machine generated. Do not edit. 🌟 -// -// Frame[0] { -// "type": "search-results", -// "typeVersion": [ -// 0, -// 0 -// ], -// "custom": { -// "count": 0 -// } -// } -// Name: Query results -// Dimensions: 8 Fields by 0 Rows -// +----------------+----------------+----------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// | Name: kind | Name: uid | Name: name | Name: panel_type | Name: url | Name: tags | Name: ds_uid | Name: location | -// | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | -// | Type: []string | Type: []string | Type: []string | Type: []string | Type: []string | Type: []*json.RawMessage | Type: []json.RawMessage | Type: []string | -// +----------------+----------------+----------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// +----------------+----------------+----------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// -// -// 🌟 This was machine generated. Do not edit. 🌟 -{ - "status": 200, - "frames": [ - { - "schema": { - "name": "Query results", - "meta": { - "type": "search-results", - "typeVersion": [ - 0, - 0 - ], - "custom": { - "count": 0 - } - }, - "fields": [ - { - "name": "kind", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "uid", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "name", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "panel_type", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "url", - "type": "string", - "typeInfo": { - "frame": "string" - }, - "config": { - "links": [ - { - "title": "link", - "url": "${__value.text}" - } - ] - } - }, - { - "name": "tags", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage", - "nullable": true - } - }, - { - "name": "ds_uid", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage" - } - }, - { - "name": "location", - "type": "string", - "typeInfo": { - "frame": "string" - } - } - ] - }, - "data": { - "values": [ - [], - [], - [], - [], - [], - [], - [], - [] - ] - } - } - ] -} \ No newline at end of file diff --git a/pkg/services/searchV2/testdata/prefix-search-beginning-lower.jsonc b/pkg/services/searchV2/testdata/prefix-search-beginning-lower.jsonc deleted file mode 100644 index 540543f0a1e..00000000000 --- a/pkg/services/searchV2/testdata/prefix-search-beginning-lower.jsonc +++ /dev/null @@ -1,139 +0,0 @@ -// 🌟 This was machine generated. Do not edit. 🌟 -// -// Frame[0] { -// "type": "search-results", -// "typeVersion": [ -// 0, -// 0 -// ], -// "custom": { -// "count": 1 -// } -// } -// Name: Query results -// Dimensions: 8 Fields by 1 Rows -// +----------------+----------------+--------------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// | Name: kind | Name: uid | Name: name | Name: panel_type | Name: url | Name: tags | Name: ds_uid | Name: location | -// | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | -// | Type: []string | Type: []string | Type: []string | Type: []string | Type: []string | Type: []*json.RawMessage | Type: []json.RawMessage | Type: []string | -// +----------------+----------------+--------------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// | dashboard | 1 | Archer Data System | | /pfix/d/1/ | null | [] | general | -// +----------------+----------------+--------------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// -// -// 🌟 This was machine generated. Do not edit. 🌟 -{ - "status": 200, - "frames": [ - { - "schema": { - "name": "Query results", - "meta": { - "type": "search-results", - "typeVersion": [ - 0, - 0 - ], - "custom": { - "count": 1 - } - }, - "fields": [ - { - "name": "kind", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "uid", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "name", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "panel_type", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "url", - "type": "string", - "typeInfo": { - "frame": "string" - }, - "config": { - "links": [ - { - "title": "link", - "url": "${__value.text}" - } - ] - } - }, - { - "name": "tags", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage", - "nullable": true - } - }, - { - "name": "ds_uid", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage" - } - }, - { - "name": "location", - "type": "string", - "typeInfo": { - "frame": "string" - } - } - ] - }, - "data": { - "values": [ - [ - "dashboard" - ], - [ - "1" - ], - [ - "Archer Data System" - ], - [ - "" - ], - [ - "/pfix/d/1/" - ], - [ - null - ], - [ - [] - ], - [ - "general" - ] - ] - } - } - ] -} \ No newline at end of file diff --git a/pkg/services/searchV2/testdata/prefix-search-beginning.jsonc b/pkg/services/searchV2/testdata/prefix-search-beginning.jsonc deleted file mode 100644 index 540543f0a1e..00000000000 --- a/pkg/services/searchV2/testdata/prefix-search-beginning.jsonc +++ /dev/null @@ -1,139 +0,0 @@ -// 🌟 This was machine generated. Do not edit. 🌟 -// -// Frame[0] { -// "type": "search-results", -// "typeVersion": [ -// 0, -// 0 -// ], -// "custom": { -// "count": 1 -// } -// } -// Name: Query results -// Dimensions: 8 Fields by 1 Rows -// +----------------+----------------+--------------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// | Name: kind | Name: uid | Name: name | Name: panel_type | Name: url | Name: tags | Name: ds_uid | Name: location | -// | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | -// | Type: []string | Type: []string | Type: []string | Type: []string | Type: []string | Type: []*json.RawMessage | Type: []json.RawMessage | Type: []string | -// +----------------+----------------+--------------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// | dashboard | 1 | Archer Data System | | /pfix/d/1/ | null | [] | general | -// +----------------+----------------+--------------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// -// -// 🌟 This was machine generated. Do not edit. 🌟 -{ - "status": 200, - "frames": [ - { - "schema": { - "name": "Query results", - "meta": { - "type": "search-results", - "typeVersion": [ - 0, - 0 - ], - "custom": { - "count": 1 - } - }, - "fields": [ - { - "name": "kind", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "uid", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "name", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "panel_type", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "url", - "type": "string", - "typeInfo": { - "frame": "string" - }, - "config": { - "links": [ - { - "title": "link", - "url": "${__value.text}" - } - ] - } - }, - { - "name": "tags", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage", - "nullable": true - } - }, - { - "name": "ds_uid", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage" - } - }, - { - "name": "location", - "type": "string", - "typeInfo": { - "frame": "string" - } - } - ] - }, - "data": { - "values": [ - [ - "dashboard" - ], - [ - "1" - ], - [ - "Archer Data System" - ], - [ - "" - ], - [ - "/pfix/d/1/" - ], - [ - null - ], - [ - [] - ], - [ - "general" - ] - ] - } - } - ] -} \ No newline at end of file diff --git a/pkg/services/searchV2/testdata/prefix-search-middle-lower.jsonc b/pkg/services/searchV2/testdata/prefix-search-middle-lower.jsonc deleted file mode 100644 index 1bcf58aa7f7..00000000000 --- a/pkg/services/searchV2/testdata/prefix-search-middle-lower.jsonc +++ /dev/null @@ -1,139 +0,0 @@ -// 🌟 This was machine generated. Do not edit. 🌟 -// -// Frame[0] { -// "type": "search-results", -// "typeVersion": [ -// 0, -// 0 -// ], -// "custom": { -// "count": 1 -// } -// } -// Name: Query results -// Dimensions: 8 Fields by 1 Rows -// +----------------+----------------+--------------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// | Name: kind | Name: uid | Name: name | Name: panel_type | Name: url | Name: tags | Name: ds_uid | Name: location | -// | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | -// | Type: []string | Type: []string | Type: []string | Type: []string | Type: []string | Type: []*json.RawMessage | Type: []json.RawMessage | Type: []string | -// +----------------+----------------+--------------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// | dashboard | 2 | Document Sync repo | | /pfix/d/2/ | null | [] | general | -// +----------------+----------------+--------------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// -// -// 🌟 This was machine generated. Do not edit. 🌟 -{ - "status": 200, - "frames": [ - { - "schema": { - "name": "Query results", - "meta": { - "type": "search-results", - "typeVersion": [ - 0, - 0 - ], - "custom": { - "count": 1 - } - }, - "fields": [ - { - "name": "kind", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "uid", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "name", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "panel_type", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "url", - "type": "string", - "typeInfo": { - "frame": "string" - }, - "config": { - "links": [ - { - "title": "link", - "url": "${__value.text}" - } - ] - } - }, - { - "name": "tags", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage", - "nullable": true - } - }, - { - "name": "ds_uid", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage" - } - }, - { - "name": "location", - "type": "string", - "typeInfo": { - "frame": "string" - } - } - ] - }, - "data": { - "values": [ - [ - "dashboard" - ], - [ - "2" - ], - [ - "Document Sync repo" - ], - [ - "" - ], - [ - "/pfix/d/2/" - ], - [ - null - ], - [ - [] - ], - [ - "general" - ] - ] - } - } - ] -} \ No newline at end of file diff --git a/pkg/services/searchV2/testdata/prefix-search-middle.jsonc b/pkg/services/searchV2/testdata/prefix-search-middle.jsonc deleted file mode 100644 index 1bcf58aa7f7..00000000000 --- a/pkg/services/searchV2/testdata/prefix-search-middle.jsonc +++ /dev/null @@ -1,139 +0,0 @@ -// 🌟 This was machine generated. Do not edit. 🌟 -// -// Frame[0] { -// "type": "search-results", -// "typeVersion": [ -// 0, -// 0 -// ], -// "custom": { -// "count": 1 -// } -// } -// Name: Query results -// Dimensions: 8 Fields by 1 Rows -// +----------------+----------------+--------------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// | Name: kind | Name: uid | Name: name | Name: panel_type | Name: url | Name: tags | Name: ds_uid | Name: location | -// | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | -// | Type: []string | Type: []string | Type: []string | Type: []string | Type: []string | Type: []*json.RawMessage | Type: []json.RawMessage | Type: []string | -// +----------------+----------------+--------------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// | dashboard | 2 | Document Sync repo | | /pfix/d/2/ | null | [] | general | -// +----------------+----------------+--------------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// -// -// 🌟 This was machine generated. Do not edit. 🌟 -{ - "status": 200, - "frames": [ - { - "schema": { - "name": "Query results", - "meta": { - "type": "search-results", - "typeVersion": [ - 0, - 0 - ], - "custom": { - "count": 1 - } - }, - "fields": [ - { - "name": "kind", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "uid", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "name", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "panel_type", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "url", - "type": "string", - "typeInfo": { - "frame": "string" - }, - "config": { - "links": [ - { - "title": "link", - "url": "${__value.text}" - } - ] - } - }, - { - "name": "tags", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage", - "nullable": true - } - }, - { - "name": "ds_uid", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage" - } - }, - { - "name": "location", - "type": "string", - "typeInfo": { - "frame": "string" - } - } - ] - }, - "data": { - "values": [ - [ - "dashboard" - ], - [ - "2" - ], - [ - "Document Sync repo" - ], - [ - "" - ], - [ - "/pfix/d/2/" - ], - [ - null - ], - [ - [] - ], - [ - "general" - ] - ] - } - } - ] -} \ No newline at end of file diff --git a/pkg/services/searchV2/testdata/prefix-search-ngram-exceeded.jsonc b/pkg/services/searchV2/testdata/prefix-search-ngram-exceeded.jsonc deleted file mode 100644 index 6fb39f3358a..00000000000 --- a/pkg/services/searchV2/testdata/prefix-search-ngram-exceeded.jsonc +++ /dev/null @@ -1,139 +0,0 @@ -// 🌟 This was machine generated. Do not edit. 🌟 -// -// Frame[0] { -// "type": "search-results", -// "typeVersion": [ -// 0, -// 0 -// ], -// "custom": { -// "count": 1 -// } -// } -// Name: Query results -// Dimensions: 8 Fields by 1 Rows -// +----------------+----------------+--------------------------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// | Name: kind | Name: uid | Name: name | Name: panel_type | Name: url | Name: tags | Name: ds_uid | Name: location | -// | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | -// | Type: []string | Type: []string | Type: []string | Type: []string | Type: []string | Type: []*json.RawMessage | Type: []json.RawMessage | Type: []string | -// +----------------+----------------+--------------------------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// | dashboard | 1 | EyjafjallajΓΆkull Eruption data | | /pfix/d/1/ | null | [] | general | -// +----------------+----------------+--------------------------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// -// -// 🌟 This was machine generated. Do not edit. 🌟 -{ - "status": 200, - "frames": [ - { - "schema": { - "name": "Query results", - "meta": { - "type": "search-results", - "typeVersion": [ - 0, - 0 - ], - "custom": { - "count": 1 - } - }, - "fields": [ - { - "name": "kind", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "uid", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "name", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "panel_type", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "url", - "type": "string", - "typeInfo": { - "frame": "string" - }, - "config": { - "links": [ - { - "title": "link", - "url": "${__value.text}" - } - ] - } - }, - { - "name": "tags", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage", - "nullable": true - } - }, - { - "name": "ds_uid", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage" - } - }, - { - "name": "location", - "type": "string", - "typeInfo": { - "frame": "string" - } - } - ] - }, - "data": { - "values": [ - [ - "dashboard" - ], - [ - "1" - ], - [ - "EyjafjallajΓΆkull Eruption data" - ], - [ - "" - ], - [ - "/pfix/d/1/" - ], - [ - null - ], - [ - [] - ], - [ - "general" - ] - ] - } - } - ] -} \ No newline at end of file diff --git a/pkg/services/searchV2/testdata/scattered-tokens-match-reversed.jsonc b/pkg/services/searchV2/testdata/scattered-tokens-match-reversed.jsonc deleted file mode 100644 index a5e0a619ad3..00000000000 --- a/pkg/services/searchV2/testdata/scattered-tokens-match-reversed.jsonc +++ /dev/null @@ -1,122 +0,0 @@ -// 🌟 This was machine generated. Do not edit. 🌟 -// -// Frame[0] { -// "type": "search-results", -// "typeVersion": [ -// 0, -// 0 -// ], -// "custom": { -// "count": 0 -// } -// } -// Name: Query results -// Dimensions: 8 Fields by 0 Rows -// +----------------+----------------+----------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// | Name: kind | Name: uid | Name: name | Name: panel_type | Name: url | Name: tags | Name: ds_uid | Name: location | -// | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | -// | Type: []string | Type: []string | Type: []string | Type: []string | Type: []string | Type: []*json.RawMessage | Type: []json.RawMessage | Type: []string | -// +----------------+----------------+----------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// +----------------+----------------+----------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// -// -// 🌟 This was machine generated. Do not edit. 🌟 -{ - "status": 200, - "frames": [ - { - "schema": { - "name": "Query results", - "meta": { - "type": "search-results", - "typeVersion": [ - 0, - 0 - ], - "custom": { - "count": 0 - } - }, - "fields": [ - { - "name": "kind", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "uid", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "name", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "panel_type", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "url", - "type": "string", - "typeInfo": { - "frame": "string" - }, - "config": { - "links": [ - { - "title": "link", - "url": "${__value.text}" - } - ] - } - }, - { - "name": "tags", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage", - "nullable": true - } - }, - { - "name": "ds_uid", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage" - } - }, - { - "name": "location", - "type": "string", - "typeInfo": { - "frame": "string" - } - } - ] - }, - "data": { - "values": [ - [], - [], - [], - [], - [], - [], - [], - [] - ] - } - } - ] -} \ No newline at end of file diff --git a/pkg/services/searchV2/testdata/scattered-tokens-match.jsonc b/pkg/services/searchV2/testdata/scattered-tokens-match.jsonc deleted file mode 100644 index 6be5a57935d..00000000000 --- a/pkg/services/searchV2/testdata/scattered-tokens-match.jsonc +++ /dev/null @@ -1,139 +0,0 @@ -// 🌟 This was machine generated. Do not edit. 🌟 -// -// Frame[0] { -// "type": "search-results", -// "typeVersion": [ -// 0, -// 0 -// ], -// "custom": { -// "count": 1 -// } -// } -// Name: Query results -// Dimensions: 8 Fields by 1 Rows -// +----------------+----------------+----------------------------------------------------------------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// | Name: kind | Name: uid | Name: name | Name: panel_type | Name: url | Name: tags | Name: ds_uid | Name: location | -// | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | -// | Type: []string | Type: []string | Type: []string | Type: []string | Type: []string | Type: []*json.RawMessage | Type: []json.RawMessage | Type: []string | -// +----------------+----------------+----------------------------------------------------------------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// | dashboard | 1 | Three can keep a secret, if two of them are dead (Benjamin Franklin) | | /pfix/d/1/ | null | [] | general | -// +----------------+----------------+----------------------------------------------------------------------+------------------+----------------+--------------------------+-------------------------+----------------+ -// -// -// 🌟 This was machine generated. Do not edit. 🌟 -{ - "status": 200, - "frames": [ - { - "schema": { - "name": "Query results", - "meta": { - "type": "search-results", - "typeVersion": [ - 0, - 0 - ], - "custom": { - "count": 1 - } - }, - "fields": [ - { - "name": "kind", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "uid", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "name", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "panel_type", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "url", - "type": "string", - "typeInfo": { - "frame": "string" - }, - "config": { - "links": [ - { - "title": "link", - "url": "${__value.text}" - } - ] - } - }, - { - "name": "tags", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage", - "nullable": true - } - }, - { - "name": "ds_uid", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage" - } - }, - { - "name": "location", - "type": "string", - "typeInfo": { - "frame": "string" - } - } - ] - }, - "data": { - "values": [ - [ - "dashboard" - ], - [ - "1" - ], - [ - "Three can keep a secret, if two of them are dead (Benjamin Franklin)" - ], - [ - "" - ], - [ - "/pfix/d/1/" - ], - [ - null - ], - [ - [] - ], - [ - "general" - ] - ] - } - } - ] -} \ No newline at end of file diff --git a/pkg/services/searchV2/testdata/search_response_frame.json b/pkg/services/searchV2/testdata/search_response_frame.json deleted file mode 100644 index 5e13fd31f4f..00000000000 --- a/pkg/services/searchV2/testdata/search_response_frame.json +++ /dev/null @@ -1,155 +0,0 @@ -{ - "schema": { - "name": "Query results", - "refId": "Search", - "meta": { - "type": "search-results", - "custom": { - "count": 106, - "locationInfo": { - "yboVMzb7z": { - "name": "gdev dashboards", - "kind": "folder", - "url": "/dashboards/f/yboVMzb7z/gdev-dashboards" - } - }, - "sortBy": "name_sort" - } - }, - "fields": [ - { - "name": "kind", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "uid", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "name", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "panel_type", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "url", - "type": "string", - "typeInfo": { - "frame": "string" - }, - "config": { - "links": [ - { - "title": "link", - "url": "${__value.text}" - } - ] - } - }, - { - "name": "tags", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage", - "nullable": true - } - }, - { - "name": "ds_uid", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage", - "nullable": false - } - }, - { - "name": "location", - "type": "string", - "typeInfo": { - "frame": "string" - } - } - ] - }, - "data": { - "values": [ - [ - "folder", - "dashboard", - "dashboard", - "dashboard" - ], - [ - "ujaM1h6nz", - "7MeksYbmk", - "vmie2cmWz", - "xMsQdBfWz" - ], - [ - "abc2", - "Alerting with TestData", - "Bar Gauge Demo", - "Bar Gauge Demo Unfilled" - ], - [ - "", - "", - "", - "" - ], - [ - "/dashboards/f/ujaM1h6nz/abc2", - "/d/7MeksYbmk/alerting-with-testdata", - "/d/vmie2cmWz/bar-gauge-demo", - "/d/xMsQdBfWz/bar-gauge-demo-unfilled" - ], - [ - null, - [ - "gdev", - "alerting" - ], - [ - "gdev", - "demo" - ], - [ - "gdev", - "demo" - ] - ], - [ - [], - [ - "datasource-1" - ], - [ - "datasource-2", - "datasource-3", - "datasource-4" - ], - [] - ], - [ - "", - "yboVMzb7z", - "yboVMzb7z", - "yboVMzb7z" - ] - ] - } -} diff --git a/pkg/services/searchV2/testdata/sort-asc.jsonc b/pkg/services/searchV2/testdata/sort-asc.jsonc deleted file mode 100644 index 7a149b5aaa9..00000000000 --- a/pkg/services/searchV2/testdata/sort-asc.jsonc +++ /dev/null @@ -1,161 +0,0 @@ -// 🌟 This was machine generated. Do not edit. 🌟 -// -// Frame[0] { -// "type": "search-results", -// "typeVersion": [ -// 0, -// 0 -// ], -// "custom": { -// "count": 2, -// "sortBy": "test" -// } -// } -// Name: Query results -// Dimensions: 9 Fields by 2 Rows -// +----------------+----------------+----------------+------------------+----------------+--------------------------+-------------------------+----------------+-----------------+ -// | Name: kind | Name: uid | Name: name | Name: panel_type | Name: url | Name: tags | Name: ds_uid | Name: location | Name: test num | -// | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | -// | Type: []string | Type: []string | Type: []string | Type: []string | Type: []string | Type: []*json.RawMessage | Type: []json.RawMessage | Type: []string | Type: []float64 | -// +----------------+----------------+----------------+------------------+----------------+--------------------------+-------------------------+----------------+-----------------+ -// | dashboard | 1 | a-test | | /pfix/d/1/ | null | [] | general | 0 | -// | dashboard | 2 | z-test | | /pfix/d/2/ | null | [] | general | 1 | -// +----------------+----------------+----------------+------------------+----------------+--------------------------+-------------------------+----------------+-----------------+ -// -// -// 🌟 This was machine generated. Do not edit. 🌟 -{ - "status": 200, - "frames": [ - { - "schema": { - "name": "Query results", - "meta": { - "type": "search-results", - "typeVersion": [ - 0, - 0 - ], - "custom": { - "count": 2, - "sortBy": "test" - } - }, - "fields": [ - { - "name": "kind", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "uid", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "name", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "panel_type", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "url", - "type": "string", - "typeInfo": { - "frame": "string" - }, - "config": { - "links": [ - { - "title": "link", - "url": "${__value.text}" - } - ] - } - }, - { - "name": "tags", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage", - "nullable": true - } - }, - { - "name": "ds_uid", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage" - } - }, - { - "name": "location", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "test num", - "type": "number", - "typeInfo": { - "frame": "float64" - } - } - ] - }, - "data": { - "values": [ - [ - "dashboard", - "dashboard" - ], - [ - "1", - "2" - ], - [ - "a-test", - "z-test" - ], - [ - "", - "" - ], - [ - "/pfix/d/1/", - "/pfix/d/2/" - ], - [ - null, - null - ], - [ - [], - [] - ], - [ - "general", - "general" - ], - [ - 0, - 1 - ] - ] - } - } - ] -} \ No newline at end of file diff --git a/pkg/services/searchV2/testdata/sort-desc.jsonc b/pkg/services/searchV2/testdata/sort-desc.jsonc deleted file mode 100644 index d0a211f6574..00000000000 --- a/pkg/services/searchV2/testdata/sort-desc.jsonc +++ /dev/null @@ -1,161 +0,0 @@ -// 🌟 This was machine generated. Do not edit. 🌟 -// -// Frame[0] { -// "type": "search-results", -// "typeVersion": [ -// 0, -// 0 -// ], -// "custom": { -// "count": 2, -// "sortBy": "test" -// } -// } -// Name: Query results -// Dimensions: 9 Fields by 2 Rows -// +----------------+----------------+----------------+------------------+----------------+--------------------------+-------------------------+----------------+-----------------+ -// | Name: kind | Name: uid | Name: name | Name: panel_type | Name: url | Name: tags | Name: ds_uid | Name: location | Name: test num | -// | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | -// | Type: []string | Type: []string | Type: []string | Type: []string | Type: []string | Type: []*json.RawMessage | Type: []json.RawMessage | Type: []string | Type: []float64 | -// +----------------+----------------+----------------+------------------+----------------+--------------------------+-------------------------+----------------+-----------------+ -// | dashboard | 2 | z-test | | /pfix/d/2/ | null | [] | general | 3 | -// | dashboard | 1 | a-test | | /pfix/d/1/ | null | [] | general | 2 | -// +----------------+----------------+----------------+------------------+----------------+--------------------------+-------------------------+----------------+-----------------+ -// -// -// 🌟 This was machine generated. Do not edit. 🌟 -{ - "status": 200, - "frames": [ - { - "schema": { - "name": "Query results", - "meta": { - "type": "search-results", - "typeVersion": [ - 0, - 0 - ], - "custom": { - "count": 2, - "sortBy": "test" - } - }, - "fields": [ - { - "name": "kind", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "uid", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "name", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "panel_type", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "url", - "type": "string", - "typeInfo": { - "frame": "string" - }, - "config": { - "links": [ - { - "title": "link", - "url": "${__value.text}" - } - ] - } - }, - { - "name": "tags", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage", - "nullable": true - } - }, - { - "name": "ds_uid", - "type": "other", - "typeInfo": { - "frame": "json.RawMessage" - } - }, - { - "name": "location", - "type": "string", - "typeInfo": { - "frame": "string" - } - }, - { - "name": "test num", - "type": "number", - "typeInfo": { - "frame": "float64" - } - } - ] - }, - "data": { - "values": [ - [ - "dashboard", - "dashboard" - ], - [ - "2", - "1" - ], - [ - "z-test", - "a-test" - ], - [ - "", - "" - ], - [ - "/pfix/d/2/", - "/pfix/d/1/" - ], - [ - null, - null - ], - [ - [], - [] - ], - [ - "general", - "general" - ], - [ - 3, - 2 - ] - ] - } - } - ] -} \ No newline at end of file diff --git a/pkg/services/searchV2/types.go b/pkg/services/searchV2/types.go deleted file mode 100644 index f66c7702b47..00000000000 --- a/pkg/services/searchV2/types.go +++ /dev/null @@ -1,50 +0,0 @@ -package searchV2 - -import ( - "context" - - "github.com/grafana/grafana-plugin-sdk-go/backend" - - "github.com/grafana/grafana/pkg/registry" - "github.com/grafana/grafana/pkg/services/user" -) - -type FacetField struct { - Field string `json:"field"` - Limit int `json:"limit,omitempty"` // explicit page size -} - -type DashboardQuery struct { - Query string `json:"query"` - Location string `json:"location,omitempty"` // parent folder ID - Sort string `json:"sort,omitempty"` // field ASC/DESC - Datasource string `json:"ds_uid,omitempty"` // "datasource" collides with the JSON value at the same level :() - DatasourceType string `json:"ds_type,omitempty"` - Tags []string `json:"tags,omitempty"` - Kind []string `json:"kind,omitempty"` - PanelType string `json:"panel_type,omitempty"` - UIDs []string `json:"uid,omitempty"` - Explain bool `json:"explain,omitempty"` // adds details on why document matched - WithAllowedActions bool `json:"withAllowedActions,omitempty"` // adds allowed actions per entity - Facet []FacetField `json:"facet,omitempty"` - SkipLocation bool `json:"skipLocation,omitempty"` - HasPreview string `json:"hasPreview,omitempty"` // the light|dark theme - Limit int `json:"limit,omitempty"` // explicit page size - From int `json:"from,omitempty"` // for paging -} - -type IsSearchReadyResponse struct { - IsReady bool - Reason string // initial-indexing-ongoing, org-indexing-ongoing -} - -//go:generate mockery --name SearchService --structname MockSearchService --inpackage --filename search_service_mock.go -type SearchService interface { - registry.CanBeDisabled - registry.BackgroundService - DoDashboardQuery(ctx context.Context, user *backend.User, orgId int64, query DashboardQuery) *backend.DataResponse - doDashboardQuery(ctx context.Context, user *user.SignedInUser, orgId int64, query DashboardQuery) *backend.DataResponse - IsReady(ctx context.Context, orgId int64) IsSearchReadyResponse - RegisterDashboardIndexExtender(ext DashboardIndexExtender) - TriggerReIndex() -} diff --git a/pkg/services/searchV2/usage.go b/pkg/services/searchV2/usage.go deleted file mode 100644 index 3bbc4a7032b..00000000000 --- a/pkg/services/searchV2/usage.go +++ /dev/null @@ -1,78 +0,0 @@ -package searchV2 - -import ( - "context" - - "github.com/blugelabs/bluge" - "github.com/blugelabs/bluge/search" - "github.com/blugelabs/bluge/search/aggregations" - "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/promauto" - - "github.com/grafana/grafana/pkg/infra/log" - "github.com/grafana/grafana/pkg/infra/tracing" -) - -type usageGauge struct { - field string - gauge *prometheus.GaugeVec -} - -var ( - infoPanelUsage = promauto.NewGaugeVec(prometheus.GaugeOpts{ - Name: "panel_type_usage", - Help: "a metric indicating how many panels across all dashboards use each plugin panel type", - Namespace: "grafana", - }, []string{"name"}) - - infoDatasourceUsage = promauto.NewGaugeVec(prometheus.GaugeOpts{ - Name: "panel_datasource_usage", - Help: "indicates how many panels across all dashboards reference each datasource type", - Namespace: "grafana", - }, []string{"name"}) - - infoTransformerUsage = promauto.NewGaugeVec(prometheus.GaugeOpts{ - Name: "panel_transformer_usage", - Help: "indicates how many panels use each transformer type", - Namespace: "grafana", - }, []string{"name"}) - - panelUsage = []usageGauge{ - {field: documentFieldDSType, gauge: infoDatasourceUsage}, - {field: documentFieldPanelType, gauge: infoPanelUsage}, - {field: documentFieldTransformer, gauge: infoTransformerUsage}, - } -) - -func updateUsageStats(ctx context.Context, reader *bluge.Reader, logger log.Logger, tracer tracing.Tracer) { - ctx, span := tracer.Start(ctx, "searchV2.updateUsageStats") - defer span.End() - req := bluge.NewAllMatches(bluge.NewTermQuery("panel").SetField(documentFieldKind)) - for _, usage := range panelUsage { - req.AddAggregation(usage.field, aggregations.NewTermsAggregation(search.Field(usage.field), 50)) - } - - // execute this search on the reader - documentMatchIterator, err := reader.Search(ctx, req) - if err != nil { - logger.Error("Error executing search", "err", err) - return - } - - // need to iterate through the document matches, otherwise the aggregations are empty? - match, err := documentMatchIterator.Next() - for err == nil && match != nil { - match, err = documentMatchIterator.Next() - } - - aggs := documentMatchIterator.Aggregations() - for _, usage := range panelUsage { - bucket := aggs.Buckets(usage.field) - for _, v := range bucket { - if v.Name() == "" { - continue - } - usage.gauge.WithLabelValues(v.Name()).Set(float64(v.Count())) - } - } -} diff --git a/pkg/services/searchV2/utils.go b/pkg/services/searchV2/utils.go deleted file mode 100644 index a5697e94940..00000000000 --- a/pkg/services/searchV2/utils.go +++ /dev/null @@ -1,39 +0,0 @@ -package searchV2 - -import ( - "fmt" - "math" - "os" - "path/filepath" -) - -func dirSize(path string) (int64, error) { - var size int64 - err := filepath.Walk(path, func(_ string, info os.FileInfo, err error) error { - if err != nil { - return err - } - if !info.IsDir() { - size += info.Size() - } - return err - }) - return size, err -} - -func logN(n, b float64) float64 { - return math.Log(n) / math.Log(b) -} - -// Slightly modified function from https://github.com/dustin/go-humanize (MIT). -func formatBytes(numBytes uint64) string { - base := 1024.0 - sizes := []string{"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB"} - if numBytes < 10 { - return fmt.Sprintf("%d B", numBytes) - } - e := math.Floor(logN(float64(numBytes), base)) - suffix := sizes[int(e)] - val := math.Floor(float64(numBytes)/math.Pow(base, e)*10+0.5) / 10 - return fmt.Sprintf("%.1f %s", val, suffix) -} diff --git a/pkg/tsdb/grafanads/grafana.go b/pkg/tsdb/grafanads/grafana.go index 68dc792342c..ffe1869e90b 100644 --- a/pkg/tsdb/grafanads/grafana.go +++ b/pkg/tsdb/grafanads/grafana.go @@ -17,7 +17,6 @@ import ( "github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/services/datasources" "github.com/grafana/grafana/pkg/services/featuremgmt" - "github.com/grafana/grafana/pkg/services/searchV2" "github.com/grafana/grafana/pkg/services/store" testdatasource "github.com/grafana/grafana/pkg/tsdb/grafana-testdata-datasource" ) @@ -53,13 +52,12 @@ var ( ) ) -func ProvideService(search searchV2.SearchService, store store.StorageService, features featuremgmt.FeatureToggles) *Service { - return newService(search, store, features) +func ProvideService(store store.StorageService, features featuremgmt.FeatureToggles) *Service { + return newService(store, features) } -func newService(search searchV2.SearchService, store store.StorageService, features featuremgmt.FeatureToggles) *Service { +func newService(store store.StorageService, features featuremgmt.FeatureToggles) *Service { s := &Service{ - search: search, store: store, log: log.New("grafanads"), features: features, @@ -70,7 +68,6 @@ func newService(search searchV2.SearchService, store store.StorageService, featu // Service exists regardless of user settings type Service struct { - search searchV2.SearchService store store.StorageService log log.Logger features featuremgmt.FeatureToggles @@ -99,8 +96,6 @@ func (s *Service) QueryData(ctx context.Context, req *backend.QueryDataRequest) response.Responses[q.RefID] = s.doListQuery(ctx, q) case queryTypeRead: response.Responses[q.RefID] = s.doReadQuery(ctx, q) - case queryTypeSearch, queryTypeSearchNext: - response.Responses[q.RefID] = s.doSearchQuery(ctx, req, q) default: response.Responses[q.RefID] = backend.DataResponse{ Error: fmt.Errorf("unknown query type"), @@ -192,34 +187,6 @@ func (s *Service) doRandomWalk(query backend.DataQuery) backend.DataResponse { return response } -func (s *Service) doSearchQuery(ctx context.Context, req *backend.QueryDataRequest, query backend.DataQuery) backend.DataResponse { - m := requestModel{} - err := json.Unmarshal(query.JSON, &m) - if err != nil { - return backend.DataResponse{ - Error: err, - } - } - - searchReadinessCheckResp := s.search.IsReady(ctx, req.PluginContext.OrgID) - if !searchReadinessCheckResp.IsReady { - dashboardSearchNotServedRequestsCounter.With(prometheus.Labels{ - "reason": searchReadinessCheckResp.Reason, - }).Inc() - - return backend.DataResponse{ - Frames: data.Frames{ - &data.Frame{ - Name: "Loading", - }, - }, - } - } - - return *s.search.DoDashboardQuery(ctx, req.PluginContext.User, req.PluginContext.OrgID, m.Search) -} - type requestModel struct { - QueryType string `json:"queryType"` - Search searchV2.DashboardQuery `json:"search,omitempty"` + QueryType string `json:"queryType"` }