diff --git a/pkg/api/annotations.go b/pkg/api/annotations.go index 0a440bb4b5b..79237b4dbd9 100644 --- a/pkg/api/annotations.go +++ b/pkg/api/annotations.go @@ -600,7 +600,7 @@ func (hs *HTTPServer) GetAnnotationTags(c *contextmodel.ReqContext) response.Res // where is the type of annotation with id . // If annotationPermissionUpdate feature toggle is enabled, dashboard annotation scope will be resolved to the corresponding // dashboard and folder scopes (eg, "dashboards:uid:", "folders:uid:" etc). -func AnnotationTypeScopeResolver(annotationsRepo annotations.Repository, features *featuremgmt.FeatureManager, dashSvc dashboards.DashboardService, folderSvc folder.Service) (string, accesscontrol.ScopeAttributeResolver) { +func AnnotationTypeScopeResolver(annotationsRepo annotations.Repository, features featuremgmt.FeatureToggles, dashSvc dashboards.DashboardService, folderSvc folder.Service) (string, accesscontrol.ScopeAttributeResolver) { prefix := accesscontrol.ScopeAnnotationsProvider.GetResourceScope("") return prefix, accesscontrol.ScopeAttributeResolverFunc(func(ctx context.Context, orgID int64, initialScope string) ([]string, error) { scopeParts := strings.Split(initialScope, ":") diff --git a/pkg/api/common_test.go b/pkg/api/common_test.go index 5ae9b45c5fa..fb408d33e1f 100644 --- a/pkg/api/common_test.go +++ b/pkg/api/common_test.go @@ -258,7 +258,7 @@ func userWithPermissions(orgID int64, permissions []accesscontrol.Permission) *u return &user.SignedInUser{IsAnonymous: true, OrgID: orgID, OrgRole: org.RoleViewer, Permissions: map[int64]map[string][]string{orgID: accesscontrol.GroupScopesByAction(permissions)}} } -func setupSimpleHTTPServer(features *featuremgmt.FeatureManager) *HTTPServer { +func setupSimpleHTTPServer(features featuremgmt.FeatureToggles) *HTTPServer { if features == nil { features = featuremgmt.WithFeatures() } diff --git a/pkg/api/datasources.go b/pkg/api/datasources.go index a7e94055505..f19534364f6 100644 --- a/pkg/api/datasources.go +++ b/pkg/api/datasources.go @@ -339,7 +339,7 @@ func validateURL(cmdType string, url string) response.Response { // validateJSONData prevents the user from adding a custom header with name that matches the auth proxy header name. // This is done to prevent data source proxy from being used to circumvent auth proxy. // For more context take a look at CVE-2022-35957 -func validateJSONData(ctx context.Context, jsonData *simplejson.Json, cfg *setting.Cfg, features *featuremgmt.FeatureManager) error { +func validateJSONData(ctx context.Context, jsonData *simplejson.Json, cfg *setting.Cfg, features featuremgmt.FeatureToggles) error { if jsonData == nil { return nil } diff --git a/pkg/api/featuremgmt.go b/pkg/api/featuremgmt.go index 6ebebf63d51..d10a5940549 100644 --- a/pkg/api/featuremgmt.go +++ b/pkg/api/featuremgmt.go @@ -25,7 +25,7 @@ func (hs *HTTPServer) GetFeatureToggles(ctx *contextmodel.ReqContext) response.R dtos := make([]featuremgmt.FeatureToggleDTO, 0) // loop through features an add features that should be visible to dtos - for _, ft := range hs.Features.GetFlags() { + for _, ft := range hs.featureManager.GetFlags() { if isFeatureHidden(ft, cfg.HiddenToggles) { continue } @@ -67,7 +67,7 @@ func (hs *HTTPServer) UpdateFeatureToggle(ctx *contextmodel.ReqContext) response for _, t := range cmd.FeatureToggles { // make sure flag exists, and only continue if flag is writeable - if f, ok := hs.Features.LookupFlag(t.Name); ok && isFeatureWriteable(f, hs.Cfg.FeatureManagement.ReadOnlyToggles) { + if f, ok := hs.featureManager.LookupFlag(t.Name); ok && isFeatureWriteable(f, hs.Cfg.FeatureManagement.ReadOnlyToggles) { hs.log.Info("UpdateFeatureToggle: updating toggle", "toggle_name", t.Name, "enabled", t.Enabled, "username", ctx.SignedInUser.Login) payload.FeatureToggles[t.Name] = strconv.FormatBool(t.Enabled) } else { @@ -82,13 +82,13 @@ func (hs *HTTPServer) UpdateFeatureToggle(ctx *contextmodel.ReqContext) response return response.Respond(http.StatusBadRequest, "Failed to perform webhook request") } - hs.Features.SetRestartRequired() + hs.featureManager.SetRestartRequired() return response.Respond(http.StatusOK, "feature toggles updated successfully") } func (hs *HTTPServer) GetFeatureMgmtState(ctx *contextmodel.ReqContext) response.Response { - fmState := hs.Features.GetState() + fmState := hs.featureManager.GetState() return response.Respond(http.StatusOK, fmState) } diff --git a/pkg/api/featuremgmt_test.go b/pkg/api/featuremgmt_test.go index 1b2b24cea12..8ce27b56584 100644 --- a/pkg/api/featuremgmt_test.go +++ b/pkg/api/featuremgmt_test.go @@ -8,6 +8,9 @@ import ( "net/http/httptest" "testing" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/featuremgmt" @@ -16,8 +19,6 @@ import ( "github.com/grafana/grafana/pkg/services/user/usertest" "github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/web/webtest" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func TestGetFeatureToggles(t *testing.T) { @@ -405,13 +406,16 @@ func runGetScenario( cfg := setting.NewCfg() cfg.FeatureManagement = settings + fm := featuremgmt.WithFeatureFlags(append([]*featuremgmt.FeatureFlag{{ + Name: featuremgmt.FlagFeatureToggleAdminPage, + Enabled: true, + Stage: featuremgmt.FeatureStageGeneralAvailability, + }}, features...)) + server := SetupAPITestServer(t, func(hs *HTTPServer) { hs.Cfg = cfg - hs.Features = featuremgmt.WithFeatureFlags(append([]*featuremgmt.FeatureFlag{{ - Name: featuremgmt.FlagFeatureToggleAdminPage, - Enabled: true, - Stage: featuremgmt.FeatureStageGeneralAvailability, - }}, features...)) + hs.Features = fm + hs.featureManager = fm hs.orgService = orgtest.NewOrgServiceFake() hs.userService = &usertest.FakeUserService{ ExpectedUser: &user.User{ID: 1}, @@ -469,13 +473,16 @@ func runSetScenario( cfg := setting.NewCfg() cfg.FeatureManagement = settings + features := featuremgmt.WithFeatureFlags(append([]*featuremgmt.FeatureFlag{{ + Name: featuremgmt.FlagFeatureToggleAdminPage, + Enabled: true, + Stage: featuremgmt.FeatureStageGeneralAvailability, + }}, serverFeatures...)) + server := SetupAPITestServer(t, func(hs *HTTPServer) { hs.Cfg = cfg - hs.Features = featuremgmt.WithFeatureFlags(append([]*featuremgmt.FeatureFlag{{ - Name: featuremgmt.FlagFeatureToggleAdminPage, - Enabled: true, - Stage: featuremgmt.FeatureStageGeneralAvailability, - }}, serverFeatures...)) + hs.Features = features + hs.featureManager = features hs.orgService = orgtest.NewOrgServiceFake() hs.userService = &usertest.FakeUserService{ ExpectedUser: &user.User{ID: 1}, diff --git a/pkg/api/folder_bench_test.go b/pkg/api/folder_bench_test.go index 93d293bc780..dd7a39289d4 100644 --- a/pkg/api/folder_bench_test.go +++ b/pkg/api/folder_bench_test.go @@ -95,7 +95,7 @@ func BenchmarkFolderListAndSearch(b *testing.B) { desc string url string expectedLen int - features *featuremgmt.FeatureManager + features featuremgmt.FeatureToggles }{ { desc: "impl=default nested_folders=on get root folders", @@ -423,7 +423,7 @@ func setupDB(b testing.TB) benchScenario { } } -func setupServer(b testing.TB, sc benchScenario, features *featuremgmt.FeatureManager) *web.Macaron { +func setupServer(b testing.TB, sc benchScenario, features featuremgmt.FeatureToggles) *web.Macaron { b.Helper() m := web.New() diff --git a/pkg/api/folder_test.go b/pkg/api/folder_test.go index d7fbfff283f..dc5b2df4458 100644 --- a/pkg/api/folder_test.go +++ b/pkg/api/folder_test.go @@ -435,7 +435,7 @@ func TestFolderGetAPIEndpoint(t *testing.T) { type testCase struct { description string URL string - features *featuremgmt.FeatureManager + features featuremgmt.FeatureToggles expectedCode int expectedParentUIDs []string expectedParentOrgIDs []int64 diff --git a/pkg/api/frontendsettings_test.go b/pkg/api/frontendsettings_test.go index 4e4e53e89a8..b14a0a63bff 100644 --- a/pkg/api/frontendsettings_test.go +++ b/pkg/api/frontendsettings_test.go @@ -32,7 +32,7 @@ import ( "github.com/grafana/grafana/pkg/web" ) -func setupTestEnvironment(t *testing.T, cfg *setting.Cfg, features *featuremgmt.FeatureManager, pstore pluginstore.Store, psettings pluginsettings.Service) (*web.Mux, *HTTPServer) { +func setupTestEnvironment(t *testing.T, cfg *setting.Cfg, features featuremgmt.FeatureToggles, pstore pluginstore.Store, psettings pluginsettings.Service) (*web.Mux, *HTTPServer) { t.Helper() db.InitTestDB(t) // nolint:staticcheck diff --git a/pkg/api/http_server.go b/pkg/api/http_server.go index f7dc7647bce..a6895f7a6ce 100644 --- a/pkg/api/http_server.go +++ b/pkg/api/http_server.go @@ -126,7 +126,8 @@ type HTTPServer struct { RouteRegister routing.RouteRegister RenderService rendering.Service Cfg *setting.Cfg - Features *featuremgmt.FeatureManager + Features featuremgmt.FeatureToggles + featureManager *featuremgmt.FeatureManager SettingsProvider setting.Provider HooksService *hooks.HooksService navTreeService navtree.Service @@ -290,7 +291,8 @@ func ProvideHTTPServer(opts ServerOptions, cfg *setting.Cfg, routeRegister routi ShortURLService: shortURLService, QueryHistoryService: queryHistoryService, CorrelationsService: correlationsService, - Features: features, + Features: features, // a read only view of the managers state + featureManager: features, StorageService: storageService, RemoteCacheService: remoteCache, ProvisioningService: provisioningService, diff --git a/pkg/infra/usagestats/statscollector/service_test.go b/pkg/infra/usagestats/statscollector/service_test.go index f3525e1c08d..7ffc509e0a1 100644 --- a/pkg/infra/usagestats/statscollector/service_test.go +++ b/pkg/infra/usagestats/statscollector/service_test.go @@ -382,7 +382,7 @@ func createService(t testing.TB, cfg *setting.Cfg, store db.DB, statsService sta store, &mockSocial{}, &pluginstore.FakePluginStore{}, - featuremgmt.WithFeatures("feature1", "feature2"), + featuremgmt.WithManager("feature1", "feature2"), o.datasources, httpclient.NewProvider(sdkhttpclient.ProviderOptions{Middlewares: []sdkhttpclient.Middleware{}}), ) diff --git a/pkg/login/social/connectors/azuread_oauth.go b/pkg/login/social/connectors/azuread_oauth.go index feba846069a..58e347f4bf7 100644 --- a/pkg/login/social/connectors/azuread_oauth.go +++ b/pkg/login/social/connectors/azuread_oauth.go @@ -72,10 +72,10 @@ type keySetJWKS struct { jose.JSONWebKeySet } -func NewAzureADProvider(info *social.OAuthInfo, cfg *setting.Cfg, ssoSettings ssosettings.Service, features *featuremgmt.FeatureManager, cache remotecache.CacheStorage) *SocialAzureAD { +func NewAzureADProvider(info *social.OAuthInfo, cfg *setting.Cfg, ssoSettings ssosettings.Service, features featuremgmt.FeatureToggles, cache remotecache.CacheStorage) *SocialAzureAD { config := createOAuthConfig(info, cfg, social.AzureADProviderName) provider := &SocialAzureAD{ - SocialBase: newSocialBase(social.AzureADProviderName, config, info, cfg.AutoAssignOrgRole, *features), + SocialBase: newSocialBase(social.AzureADProviderName, config, info, cfg.AutoAssignOrgRole, features), cache: cache, allowedOrganizations: util.SplitString(info.Extra[allowedOrganizationsKey]), forceUseGraphAPI: MustBool(info.Extra[forceUseGraphAPIKey], false), diff --git a/pkg/login/social/connectors/generic_oauth.go b/pkg/login/social/connectors/generic_oauth.go index 156ec78910f..6fd98b60e9f 100644 --- a/pkg/login/social/connectors/generic_oauth.go +++ b/pkg/login/social/connectors/generic_oauth.go @@ -45,10 +45,10 @@ type SocialGenericOAuth struct { teamIds []string } -func NewGenericOAuthProvider(info *social.OAuthInfo, cfg *setting.Cfg, ssoSettings ssosettings.Service, features *featuremgmt.FeatureManager) *SocialGenericOAuth { +func NewGenericOAuthProvider(info *social.OAuthInfo, cfg *setting.Cfg, ssoSettings ssosettings.Service, features featuremgmt.FeatureToggles) *SocialGenericOAuth { config := createOAuthConfig(info, cfg, social.GenericOAuthProviderName) provider := &SocialGenericOAuth{ - SocialBase: newSocialBase(social.GenericOAuthProviderName, config, info, cfg.AutoAssignOrgRole, *features), + SocialBase: newSocialBase(social.GenericOAuthProviderName, config, info, cfg.AutoAssignOrgRole, features), teamsUrl: info.TeamsUrl, emailAttributeName: info.EmailAttributeName, emailAttributePath: info.EmailAttributePath, diff --git a/pkg/login/social/connectors/github_oauth.go b/pkg/login/social/connectors/github_oauth.go index cac4942b73b..5863b453d45 100644 --- a/pkg/login/social/connectors/github_oauth.go +++ b/pkg/login/social/connectors/github_oauth.go @@ -53,13 +53,13 @@ var ( "User is not a member of one of the required organizations. Please contact identity provider administrator.")) ) -func NewGitHubProvider(info *social.OAuthInfo, cfg *setting.Cfg, ssoSettings ssosettings.Service, features *featuremgmt.FeatureManager) *SocialGithub { +func NewGitHubProvider(info *social.OAuthInfo, cfg *setting.Cfg, ssoSettings ssosettings.Service, features featuremgmt.FeatureToggles) *SocialGithub { teamIdsSplitted := util.SplitString(info.Extra[teamIdsKey]) teamIds := mustInts(teamIdsSplitted) config := createOAuthConfig(info, cfg, social.GitHubProviderName) provider := &SocialGithub{ - SocialBase: newSocialBase(social.GitHubProviderName, config, info, cfg.AutoAssignOrgRole, *features), + SocialBase: newSocialBase(social.GitHubProviderName, config, info, cfg.AutoAssignOrgRole, features), teamIds: teamIds, allowedOrganizations: util.SplitString(info.Extra[allowedOrganizationsKey]), } diff --git a/pkg/login/social/connectors/gitlab_oauth.go b/pkg/login/social/connectors/gitlab_oauth.go index 850083ad8e7..385882a8a6f 100644 --- a/pkg/login/social/connectors/gitlab_oauth.go +++ b/pkg/login/social/connectors/gitlab_oauth.go @@ -52,10 +52,10 @@ type userData struct { IsGrafanaAdmin *bool `json:"-"` } -func NewGitLabProvider(info *social.OAuthInfo, cfg *setting.Cfg, ssoSettings ssosettings.Service, features *featuremgmt.FeatureManager) *SocialGitlab { +func NewGitLabProvider(info *social.OAuthInfo, cfg *setting.Cfg, ssoSettings ssosettings.Service, features featuremgmt.FeatureToggles) *SocialGitlab { config := createOAuthConfig(info, cfg, social.GitlabProviderName) provider := &SocialGitlab{ - SocialBase: newSocialBase(social.GitlabProviderName, config, info, cfg.AutoAssignOrgRole, *features), + SocialBase: newSocialBase(social.GitlabProviderName, config, info, cfg.AutoAssignOrgRole, features), } if features.IsEnabledGlobally(featuremgmt.FlagSsoSettingsApi) { diff --git a/pkg/login/social/connectors/google_oauth.go b/pkg/login/social/connectors/google_oauth.go index 440ebb5e432..36849984755 100644 --- a/pkg/login/social/connectors/google_oauth.go +++ b/pkg/login/social/connectors/google_oauth.go @@ -38,10 +38,10 @@ type googleUserData struct { rawJSON []byte `json:"-"` } -func NewGoogleProvider(info *social.OAuthInfo, cfg *setting.Cfg, ssoSettings ssosettings.Service, features *featuremgmt.FeatureManager) *SocialGoogle { +func NewGoogleProvider(info *social.OAuthInfo, cfg *setting.Cfg, ssoSettings ssosettings.Service, features featuremgmt.FeatureToggles) *SocialGoogle { config := createOAuthConfig(info, cfg, social.GoogleProviderName) provider := &SocialGoogle{ - SocialBase: newSocialBase(social.GoogleProviderName, config, info, cfg.AutoAssignOrgRole, *features), + SocialBase: newSocialBase(social.GoogleProviderName, config, info, cfg.AutoAssignOrgRole, features), } if strings.HasPrefix(info.ApiUrl, legacyAPIURL) { diff --git a/pkg/login/social/connectors/grafana_com_oauth.go b/pkg/login/social/connectors/grafana_com_oauth.go index a32ad8be3cc..276548447ff 100644 --- a/pkg/login/social/connectors/grafana_com_oauth.go +++ b/pkg/login/social/connectors/grafana_com_oauth.go @@ -33,7 +33,7 @@ type OrgRecord struct { Login string `json:"login"` } -func NewGrafanaComProvider(info *social.OAuthInfo, cfg *setting.Cfg, ssoSettings ssosettings.Service, features *featuremgmt.FeatureManager) *SocialGrafanaCom { +func NewGrafanaComProvider(info *social.OAuthInfo, cfg *setting.Cfg, ssoSettings ssosettings.Service, features featuremgmt.FeatureToggles) *SocialGrafanaCom { // Override necessary settings info.AuthUrl = cfg.GrafanaComURL + "/oauth2/authorize" info.TokenUrl = cfg.GrafanaComURL + "/api/oauth2/token" @@ -41,7 +41,7 @@ func NewGrafanaComProvider(info *social.OAuthInfo, cfg *setting.Cfg, ssoSettings config := createOAuthConfig(info, cfg, social.GrafanaComProviderName) provider := &SocialGrafanaCom{ - SocialBase: newSocialBase(social.GrafanaComProviderName, config, info, cfg.AutoAssignOrgRole, *features), + SocialBase: newSocialBase(social.GrafanaComProviderName, config, info, cfg.AutoAssignOrgRole, features), url: cfg.GrafanaComURL, allowedOrganizations: util.SplitString(info.Extra[allowedOrganizationsKey]), } diff --git a/pkg/login/social/connectors/okta_oauth.go b/pkg/login/social/connectors/okta_oauth.go index 4de9bcca9ec..84a791db155 100644 --- a/pkg/login/social/connectors/okta_oauth.go +++ b/pkg/login/social/connectors/okta_oauth.go @@ -44,10 +44,10 @@ type OktaClaims struct { Name string `json:"name"` } -func NewOktaProvider(info *social.OAuthInfo, cfg *setting.Cfg, ssoSettings ssosettings.Service, features *featuremgmt.FeatureManager) *SocialOkta { +func NewOktaProvider(info *social.OAuthInfo, cfg *setting.Cfg, ssoSettings ssosettings.Service, features featuremgmt.FeatureToggles) *SocialOkta { config := createOAuthConfig(info, cfg, social.OktaProviderName) provider := &SocialOkta{ - SocialBase: newSocialBase(social.OktaProviderName, config, info, cfg.AutoAssignOrgRole, *features), + SocialBase: newSocialBase(social.OktaProviderName, config, info, cfg.AutoAssignOrgRole, features), } if info.UseRefreshToken { diff --git a/pkg/login/social/connectors/social_base.go b/pkg/login/social/connectors/social_base.go index f8ecd5216b3..e5a9ce5c211 100644 --- a/pkg/login/social/connectors/social_base.go +++ b/pkg/login/social/connectors/social_base.go @@ -26,14 +26,14 @@ type SocialBase struct { info *social.OAuthInfo log log.Logger autoAssignOrgRole string - features featuremgmt.FeatureManager + features featuremgmt.FeatureToggles } func newSocialBase(name string, config *oauth2.Config, info *social.OAuthInfo, autoAssignOrgRole string, - features featuremgmt.FeatureManager, + features featuremgmt.FeatureToggles, ) *SocialBase { logger := log.New("oauth." + name) diff --git a/pkg/login/social/socialimpl/service.go b/pkg/login/social/socialimpl/service.go index 30893daca07..b62201c3bd9 100644 --- a/pkg/login/social/socialimpl/service.go +++ b/pkg/login/social/socialimpl/service.go @@ -37,7 +37,7 @@ type SocialService struct { } func ProvideService(cfg *setting.Cfg, - features *featuremgmt.FeatureManager, + features featuremgmt.FeatureToggles, usageStats usagestats.Service, bundleRegistry supportbundles.Service, cache remotecache.CacheStorage, @@ -228,7 +228,7 @@ func (ss *SocialService) getUsageStats(ctx context.Context) (map[string]any, err return m, nil } -func createOAuthConnector(name string, info *social.OAuthInfo, cfg *setting.Cfg, ssoSettings ssosettings.Service, features *featuremgmt.FeatureManager, cache remotecache.CacheStorage) (social.SocialConnector, error) { +func createOAuthConnector(name string, info *social.OAuthInfo, cfg *setting.Cfg, ssoSettings ssosettings.Service, features featuremgmt.FeatureToggles, cache remotecache.CacheStorage) (social.SocialConnector, error) { switch name { case social.AzureADProviderName: return connectors.NewAzureADProvider(info, cfg, ssoSettings, features, cache), nil diff --git a/pkg/login/social/socialimpl/service_test.go b/pkg/login/social/socialimpl/service_test.go index fe3d885fedd..e708f74129d 100644 --- a/pkg/login/social/socialimpl/service_test.go +++ b/pkg/login/social/socialimpl/service_test.go @@ -22,7 +22,7 @@ import ( func TestSocialService_ProvideService(t *testing.T) { type testEnv struct { - features *featuremgmt.FeatureManager + features featuremgmt.FeatureToggles } testCases := []struct { name string diff --git a/pkg/plugins/config/config.go b/pkg/plugins/config/config.go index f96aa769ad8..bedd5cd45f4 100644 --- a/pkg/plugins/config/config.go +++ b/pkg/plugins/config/config.go @@ -3,8 +3,8 @@ package config import ( "github.com/grafana/grafana-azure-sdk-go/azsettings" - "github.com/grafana/grafana/pkg/plugins" "github.com/grafana/grafana/pkg/plugins/log" + "github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/setting" ) @@ -44,7 +44,7 @@ type Cfg struct { GrafanaAppURL string GrafanaAppSubURL string - Features plugins.FeatureToggles + Features featuremgmt.FeatureToggles AngularSupportEnabled bool HideAngularDeprecation []string @@ -52,7 +52,7 @@ type Cfg struct { func NewCfg(devMode bool, pluginsPath string, pluginSettings setting.PluginSettings, pluginsAllowUnsigned []string, awsAllowedAuthProviders []string, awsAssumeRoleEnabled bool, awsExternalId string, azure *azsettings.AzureSettings, secureSocksDSProxy setting.SecureSocksDSProxySettings, - grafanaVersion string, logDatasourceRequests bool, pluginsCDNURLTemplate string, appURL string, appSubURL string, tracing Tracing, features plugins.FeatureToggles, angularSupportEnabled bool, + grafanaVersion string, logDatasourceRequests bool, pluginsCDNURLTemplate string, appURL string, appSubURL string, tracing Tracing, features featuremgmt.FeatureToggles, angularSupportEnabled bool, grafanaComURL string, disablePlugins []string, hideAngularDeprecation []string, forwardHostEnvVars []string) *Cfg { return &Cfg{ log: log.New("plugin.cfg"), diff --git a/pkg/plugins/envvars/envvars_test.go b/pkg/plugins/envvars/envvars_test.go index daf8df83c75..0c9069497dc 100644 --- a/pkg/plugins/envvars/envvars_test.go +++ b/pkg/plugins/envvars/envvars_test.go @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/require" "github.com/grafana/grafana-azure-sdk-go/azsettings" + "github.com/grafana/grafana/pkg/plugins" "github.com/grafana/grafana/pkg/plugins/auth" "github.com/grafana/grafana/pkg/plugins/config" @@ -726,35 +727,35 @@ func TestService_GetConfigMap(t *testing.T) { func TestService_GetConfigMap_featureToggles(t *testing.T) { t.Run("Feature toggles list is deterministic", func(t *testing.T) { tcs := []struct { - enabledFeatures []string - expectedConfig map[string]string + features featuremgmt.FeatureToggles + expectedConfig map[string]string }{ { - enabledFeatures: nil, - expectedConfig: map[string]string{}, + features: nil, + expectedConfig: map[string]string{}, }, { - enabledFeatures: []string{}, - expectedConfig: map[string]string{}, + features: featuremgmt.WithFeatures(), + expectedConfig: map[string]string{}, }, { - enabledFeatures: []string{"A", "B", "C"}, - expectedConfig: map[string]string{"GF_INSTANCE_FEATURE_TOGGLES_ENABLE": "A,B,C"}, + features: featuremgmt.WithFeatures("A", "B", "C"), + expectedConfig: map[string]string{"GF_INSTANCE_FEATURE_TOGGLES_ENABLE": "A,B,C"}, }, { - enabledFeatures: []string{"C", "B", "A"}, - expectedConfig: map[string]string{"GF_INSTANCE_FEATURE_TOGGLES_ENABLE": "A,B,C"}, + features: featuremgmt.WithFeatures("C", "B", "A"), + expectedConfig: map[string]string{"GF_INSTANCE_FEATURE_TOGGLES_ENABLE": "A,B,C"}, }, { - enabledFeatures: []string{"b", "a", "c", "d"}, - expectedConfig: map[string]string{"GF_INSTANCE_FEATURE_TOGGLES_ENABLE": "a,b,c,d"}, + features: featuremgmt.WithFeatures("b", "a", "c", "d"), + expectedConfig: map[string]string{"GF_INSTANCE_FEATURE_TOGGLES_ENABLE": "a,b,c,d"}, }, } for _, tc := range tcs { s := &Service{ cfg: &config.Cfg{ - Features: fakes.NewFakeFeatureToggles(tc.enabledFeatures...), + Features: tc.features, }, } require.Equal(t, tc.expectedConfig, s.GetConfigMap(context.Background(), "", nil)) diff --git a/pkg/plugins/ifaces.go b/pkg/plugins/ifaces.go index a81e18c409a..00fe2bc7f74 100644 --- a/pkg/plugins/ifaces.go +++ b/pkg/plugins/ifaces.go @@ -149,11 +149,6 @@ func (fn ClientMiddlewareFunc) CreateClientMiddleware(next Client) Client { return fn(next) } -type FeatureToggles interface { - IsEnabledGlobally(flag string) bool - GetEnabled(ctx context.Context) map[string]bool -} - type SignatureCalculator interface { Calculate(ctx context.Context, src PluginSource, plugin FoundPlugin) (Signature, error) } diff --git a/pkg/plugins/manager/fakes/fakes.go b/pkg/plugins/manager/fakes/fakes.go index 9b950274da6..e460cef4ef9 100644 --- a/pkg/plugins/manager/fakes/fakes.go +++ b/pkg/plugins/manager/fakes/fakes.go @@ -574,26 +574,3 @@ func (p *FakeBackendPlugin) Kill() { defer p.mutex.Unlock() p.Running = false } - -type FakeFeatureToggles struct { - features map[string]bool -} - -func NewFakeFeatureToggles(features ...string) *FakeFeatureToggles { - m := make(map[string]bool) - for _, f := range features { - m[f] = true - } - - return &FakeFeatureToggles{ - features: m, - } -} - -func (f *FakeFeatureToggles) GetEnabled(_ context.Context) map[string]bool { - return f.features -} - -func (f *FakeFeatureToggles) IsEnabledGlobally(feature string) bool { - return f.features[feature] -} diff --git a/pkg/plugins/manager/loader/finder/local.go b/pkg/plugins/manager/loader/finder/local.go index aab9712f91e..75c4a7e9a75 100644 --- a/pkg/plugins/manager/loader/finder/local.go +++ b/pkg/plugins/manager/loader/finder/local.go @@ -26,10 +26,10 @@ var ( type Local struct { log log.Logger production bool - features plugins.FeatureToggles + features featuremgmt.FeatureToggles } -func NewLocalFinder(devMode bool, features plugins.FeatureToggles) *Local { +func NewLocalFinder(devMode bool, features featuremgmt.FeatureToggles) *Local { return &Local{ production: !devMode, log: log.New("local.finder"), diff --git a/pkg/services/accesscontrol/acimpl/service.go b/pkg/services/accesscontrol/acimpl/service.go index ac51ecc0f8b..fa6471a8ca8 100644 --- a/pkg/services/accesscontrol/acimpl/service.go +++ b/pkg/services/accesscontrol/acimpl/service.go @@ -41,7 +41,7 @@ var SharedWithMeFolderPermission = accesscontrol.Permission{ } func ProvideService(cfg *setting.Cfg, db db.DB, routeRegister routing.RouteRegister, cache *localcache.CacheService, - accessControl accesscontrol.AccessControl, features *featuremgmt.FeatureManager) (*Service, error) { + accessControl accesscontrol.AccessControl, features featuremgmt.FeatureToggles) (*Service, error) { service := ProvideOSSService(cfg, database.ProvideService(db), cache, features) api.NewAccessControlAPI(routeRegister, accessControl, service, features).RegisterAPIEndpoints() @@ -62,7 +62,7 @@ func ProvideService(cfg *setting.Cfg, db db.DB, routeRegister routing.RouteRegis return service, nil } -func ProvideOSSService(cfg *setting.Cfg, store store, cache *localcache.CacheService, features *featuremgmt.FeatureManager) *Service { +func ProvideOSSService(cfg *setting.Cfg, store store, cache *localcache.CacheService, features featuremgmt.FeatureToggles) *Service { s := &Service{ cfg: cfg, store: store, @@ -93,7 +93,7 @@ type Service struct { cache *localcache.CacheService registrations accesscontrol.RegistrationList roles map[string]*accesscontrol.RoleDTO - features *featuremgmt.FeatureManager + features featuremgmt.FeatureToggles } func (s *Service) GetUsageStats(_ context.Context) map[string]any { diff --git a/pkg/services/accesscontrol/api/api.go b/pkg/services/accesscontrol/api/api.go index 241d367c88a..692cdc4df1f 100644 --- a/pkg/services/accesscontrol/api/api.go +++ b/pkg/services/accesscontrol/api/api.go @@ -15,7 +15,7 @@ import ( ) func NewAccessControlAPI(router routing.RouteRegister, accesscontrol ac.AccessControl, service ac.Service, - features *featuremgmt.FeatureManager) *AccessControlAPI { + features featuremgmt.FeatureToggles) *AccessControlAPI { return &AccessControlAPI{ RouteRegister: router, Service: service, @@ -28,7 +28,7 @@ type AccessControlAPI struct { Service ac.Service AccessControl ac.AccessControl RouteRegister routing.RouteRegister - features *featuremgmt.FeatureManager + features featuremgmt.FeatureToggles } func (api *AccessControlAPI) RegisterAPIEndpoints() { diff --git a/pkg/services/authn/clients/session.go b/pkg/services/authn/clients/session.go index dc8219c0240..03339f193fa 100644 --- a/pkg/services/authn/clients/session.go +++ b/pkg/services/authn/clients/session.go @@ -19,7 +19,7 @@ var _ authn.HookClient = new(Session) var _ authn.ContextAwareClient = new(Session) func ProvideSession(cfg *setting.Cfg, sessionService auth.UserTokenService, - features *featuremgmt.FeatureManager) *Session { + features featuremgmt.FeatureToggles) *Session { return &Session{ cfg: cfg, features: features, @@ -30,7 +30,7 @@ func ProvideSession(cfg *setting.Cfg, sessionService auth.UserTokenService, type Session struct { cfg *setting.Cfg - features *featuremgmt.FeatureManager + features featuremgmt.FeatureToggles sessionService auth.UserTokenService log log.Logger } diff --git a/pkg/services/authn/clients/session_test.go b/pkg/services/authn/clients/session_test.go index 8dd7555cd26..7e8a3954f10 100644 --- a/pkg/services/authn/clients/session_test.go +++ b/pkg/services/authn/clients/session_test.go @@ -64,7 +64,7 @@ func TestSession_Authenticate(t *testing.T) { type fields struct { sessionService auth.UserTokenService - features *featuremgmt.FeatureManager + features featuremgmt.FeatureToggles } type args struct { r *authn.Request diff --git a/pkg/services/contexthandler/contexthandler.go b/pkg/services/contexthandler/contexthandler.go index 49b91f45f4f..3b83863da62 100644 --- a/pkg/services/contexthandler/contexthandler.go +++ b/pkg/services/contexthandler/contexthandler.go @@ -25,7 +25,7 @@ import ( "github.com/grafana/grafana/pkg/web" ) -func ProvideService(cfg *setting.Cfg, tracer tracing.Tracer, features *featuremgmt.FeatureManager, authnService authn.Service, +func ProvideService(cfg *setting.Cfg, tracer tracing.Tracer, features featuremgmt.FeatureToggles, authnService authn.Service, ) *ContextHandler { return &ContextHandler{ Cfg: cfg, @@ -39,7 +39,7 @@ func ProvideService(cfg *setting.Cfg, tracer tracing.Tracer, features *featuremg type ContextHandler struct { Cfg *setting.Cfg tracer tracing.Tracer - features *featuremgmt.FeatureManager + features featuremgmt.FeatureToggles authnService authn.Service } diff --git a/pkg/services/featuremgmt/manager.go b/pkg/services/featuremgmt/manager.go index b2c962dc1c2..3c6be92bb17 100644 --- a/pkg/services/featuremgmt/manager.go +++ b/pkg/services/featuremgmt/manager.go @@ -174,10 +174,14 @@ func (fm *FeatureManager) LookupFlag(name string) (FeatureFlag, bool) { // ############# Test Functions ############# +func WithFeatures(spec ...any) FeatureToggles { + return WithManager(spec...) +} + // WithFeatures is used to define feature toggles for testing. // The arguments are a list of strings that are optionally followed by a boolean value for example: // WithFeatures([]any{"my_feature", "other_feature"}) or WithFeatures([]any{"my_feature", true}) -func WithFeatures(spec ...any) *FeatureManager { +func WithManager(spec ...any) *FeatureManager { count := len(spec) features := make(map[string]*FeatureFlag, count) enabled := make(map[string]bool, count) diff --git a/pkg/services/featuremgmt/manager_test.go b/pkg/services/featuremgmt/manager_test.go index 83bdd73995d..eed91b011d7 100644 --- a/pkg/services/featuremgmt/manager_test.go +++ b/pkg/services/featuremgmt/manager_test.go @@ -9,7 +9,7 @@ import ( func TestFeatureManager(t *testing.T) { t.Run("check testing stubs", func(t *testing.T) { - ft := WithFeatures("a", "b", "c") + ft := WithManager("a", "b", "c") require.True(t, ft.IsEnabledGlobally("a")) require.True(t, ft.IsEnabledGlobally("b")) require.True(t, ft.IsEnabledGlobally("c")) @@ -18,7 +18,7 @@ func TestFeatureManager(t *testing.T) { require.Equal(t, map[string]bool{"a": true, "b": true, "c": true}, ft.GetEnabled(context.Background())) // Explicit values - ft = WithFeatures("a", true, "b", false) + ft = WithManager("a", true, "b", false) require.True(t, ft.IsEnabledGlobally("a")) require.False(t, ft.IsEnabledGlobally("b")) require.Equal(t, map[string]bool{"a": true}, ft.GetEnabled(context.Background())) diff --git a/pkg/services/featuremgmt/models.go b/pkg/services/featuremgmt/models.go index 7c950f1e820..f52fbc24b8d 100644 --- a/pkg/services/featuremgmt/models.go +++ b/pkg/services/featuremgmt/models.go @@ -18,6 +18,10 @@ type FeatureToggles interface { // Use of global feature flags should be limited and careful as they require // a full server restart for a change to take place. IsEnabledGlobally(flag string) bool + + // Get the enabled flags -- this *may* also include disabled flags (with value false) + // but it is guaranteed to have the enabled ones listed + GetEnabled(ctx context.Context) map[string]bool } // FeatureFlagStage indicates the quality level diff --git a/pkg/services/featuremgmt/usage_stats_test.go b/pkg/services/featuremgmt/usage_stats_test.go index 03c7fe0c2df..a24b86cbef6 100644 --- a/pkg/services/featuremgmt/usage_stats_test.go +++ b/pkg/services/featuremgmt/usage_stats_test.go @@ -8,7 +8,7 @@ import ( ) func TestFeatureUsageStats(t *testing.T) { - featureManagerWithAllFeatures := WithFeatures( + featureManagerWithAllFeatures := WithManager( "database_metrics", "live-config", "UPPER_SNAKE_CASE", diff --git a/pkg/services/folder/folderimpl/folder_test.go b/pkg/services/folder/folderimpl/folder_test.go index e0e68da3b6f..ff4c643002f 100644 --- a/pkg/services/folder/folderimpl/folder_test.go +++ b/pkg/services/folder/folderimpl/folder_test.go @@ -587,7 +587,7 @@ func TestIntegrationNestedFolderService(t *testing.T) { testCases := []struct { service *Service - featuresFlag *featuremgmt.FeatureManager + featuresFlag featuremgmt.FeatureToggles prefix string depth int forceDelete bool diff --git a/pkg/services/navtree/navtreeimpl/navtree.go b/pkg/services/navtree/navtreeimpl/navtree.go index 5e1201f7fe2..20e56c7865d 100644 --- a/pkg/services/navtree/navtreeimpl/navtree.go +++ b/pkg/services/navtree/navtreeimpl/navtree.go @@ -33,7 +33,7 @@ type ServiceImpl struct { pluginStore pluginstore.Store pluginSettings pluginsettings.Service starService star.Service - features *featuremgmt.FeatureManager + features featuremgmt.FeatureToggles dashboardService dashboards.DashboardService accesscontrolService ac.Service kvStore kvstore.KVStore @@ -52,7 +52,7 @@ type NavigationAppConfig struct { Icon string } -func ProvideService(cfg *setting.Cfg, accessControl ac.AccessControl, pluginStore pluginstore.Store, pluginSettings pluginsettings.Service, starService star.Service, features *featuremgmt.FeatureManager, dashboardService dashboards.DashboardService, accesscontrolService ac.Service, kvStore kvstore.KVStore, apiKeyService apikey.Service, license licensing.Licensing) navtree.Service { +func ProvideService(cfg *setting.Cfg, accessControl ac.AccessControl, pluginStore pluginstore.Store, pluginSettings pluginsettings.Service, starService star.Service, features featuremgmt.FeatureToggles, dashboardService dashboards.DashboardService, accesscontrolService ac.Service, kvStore kvstore.KVStore, apiKeyService apikey.Service, license licensing.Licensing) navtree.Service { service := &ServiceImpl{ cfg: cfg, log: log.New("navtree service"), diff --git a/pkg/services/pluginsintegration/clientmiddleware/caching_middleware.go b/pkg/services/pluginsintegration/clientmiddleware/caching_middleware.go index 3bc00043462..f77b8f100bb 100644 --- a/pkg/services/pluginsintegration/clientmiddleware/caching_middleware.go +++ b/pkg/services/pluginsintegration/clientmiddleware/caching_middleware.go @@ -27,7 +27,7 @@ func NewCachingMiddleware(cachingService caching.CachingService) plugins.ClientM // NewCachingMiddlewareWithFeatureManager creates a new plugins.ClientMiddleware that will // attempt to read and write query results to the cache with a feature manager -func NewCachingMiddlewareWithFeatureManager(cachingService caching.CachingService, features *featuremgmt.FeatureManager) plugins.ClientMiddleware { +func NewCachingMiddlewareWithFeatureManager(cachingService caching.CachingService, features featuremgmt.FeatureToggles) plugins.ClientMiddleware { log := log.New("caching_middleware") if err := prometheus.Register(QueryCachingRequestHistogram); err != nil { log.Error("Error registering prometheus collector 'QueryRequestHistogram'", "error", err) @@ -49,7 +49,7 @@ type CachingMiddleware struct { next plugins.Client caching caching.CachingService log log.Logger - features *featuremgmt.FeatureManager + features featuremgmt.FeatureToggles } // QueryData receives a data request and attempts to access results already stored in the cache for that request. diff --git a/pkg/services/pluginsintegration/config/config.go b/pkg/services/pluginsintegration/config/config.go index cabd7d4a398..50056ce54f3 100644 --- a/pkg/services/pluginsintegration/config/config.go +++ b/pkg/services/pluginsintegration/config/config.go @@ -9,7 +9,7 @@ import ( "github.com/grafana/grafana/pkg/setting" ) -func ProvideConfig(settingProvider setting.Provider, grafanaCfg *setting.Cfg, features *featuremgmt.FeatureManager) (*pCfg.Cfg, error) { +func ProvideConfig(settingProvider setting.Provider, grafanaCfg *setting.Cfg, features featuremgmt.FeatureToggles) (*pCfg.Cfg, error) { plugins := settingProvider.Section("plugins") allowedUnsigned := grafanaCfg.PluginsAllowUnsigned if len(plugins.KeyValue("allow_loading_unsigned_plugins").Value()) > 0 { diff --git a/pkg/services/pluginsintegration/loader/loader_test.go b/pkg/services/pluginsintegration/loader/loader_test.go index 1f3386851ee..13ff672ba76 100644 --- a/pkg/services/pluginsintegration/loader/loader_test.go +++ b/pkg/services/pluginsintegration/loader/loader_test.go @@ -507,7 +507,7 @@ func TestLoader_Load_ExternalRegistration(t *testing.T) { t.Run("Load a plugin with oauth client registration", func(t *testing.T) { cfg := &config.Cfg{ - Features: fakes.NewFakeFeatureToggles(featuremgmt.FlagExternalServiceAuth), + Features: featuremgmt.WithFeatures(featuremgmt.FlagExternalServiceAuth), PluginsAllowUnsigned: []string{"grafana-test-datasource"}, } pluginPaths := []string{filepath.Join(testDataDir(t), "oauth-external-registration")} @@ -608,7 +608,7 @@ func TestLoader_Load_ExternalRegistration(t *testing.T) { t.Run("Load a plugin with service account registration", func(t *testing.T) { cfg := &config.Cfg{ - Features: fakes.NewFakeFeatureToggles(featuremgmt.FlagExternalServiceAuth), + Features: featuremgmt.WithFeatures(featuremgmt.FlagExternalServiceAuth), PluginsAllowUnsigned: []string{"grafana-test-datasource"}, } pluginPaths := []string{filepath.Join(testDataDir(t), "external-registration")} diff --git a/pkg/services/pluginsintegration/pipeline/steps_test.go b/pkg/services/pluginsintegration/pipeline/steps_test.go index 98c665d0d10..5ceb015fef4 100644 --- a/pkg/services/pluginsintegration/pipeline/steps_test.go +++ b/pkg/services/pluginsintegration/pipeline/steps_test.go @@ -3,12 +3,13 @@ package pipeline import ( "testing" + "github.com/stretchr/testify/require" + "github.com/grafana/grafana/pkg/plugins" "github.com/grafana/grafana/pkg/plugins/config" "github.com/grafana/grafana/pkg/plugins/log" "github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/setting" - "github.com/stretchr/testify/require" ) func TestSkipPlugins(t *testing.T) { diff --git a/pkg/services/publicdashboards/api/api.go b/pkg/services/publicdashboards/api/api.go index 77fa58df291..d65ac5b13e5 100644 --- a/pkg/services/publicdashboards/api/api.go +++ b/pkg/services/publicdashboards/api/api.go @@ -27,7 +27,7 @@ type Api struct { accessControl accesscontrol.AccessControl cfg *setting.Cfg - features *featuremgmt.FeatureManager + features featuremgmt.FeatureToggles log log.Logger routeRegister routing.RouteRegister } @@ -36,7 +36,7 @@ func ProvideApi( pd publicdashboards.Service, rr routing.RouteRegister, ac accesscontrol.AccessControl, - features *featuremgmt.FeatureManager, + features featuremgmt.FeatureToggles, md publicdashboards.Middleware, cfg *setting.Cfg, ) *Api { @@ -297,7 +297,7 @@ func (api *Api) DeletePublicDashboard(c *contextmodel.ReqContext) response.Respo } // Copied from pkg/api/metrics.go -func toJsonStreamingResponse(ctx context.Context, features *featuremgmt.FeatureManager, qdr *backend.QueryDataResponse) response.Response { +func toJsonStreamingResponse(ctx context.Context, features featuremgmt.FeatureToggles, qdr *backend.QueryDataResponse) response.Response { statusWhenError := http.StatusBadRequest if features.IsEnabled(ctx, featuremgmt.FlagDatasourceQueryMultiStatus) { statusWhenError = http.StatusMultiStatus diff --git a/pkg/services/secrets/kvstore/test_helpers.go b/pkg/services/secrets/kvstore/test_helpers.go index c790446a7b3..768a94d7085 100644 --- a/pkg/services/secrets/kvstore/test_helpers.go +++ b/pkg/services/secrets/kvstore/test_helpers.go @@ -155,6 +155,10 @@ func (f fakeFeatureToggles) IsEnabled(ctx context.Context, feature string) bool return f.returnValue } +func (f fakeFeatureToggles) GetEnabled(ctx context.Context) map[string]bool { + return map[string]bool{} +} + // Fake grpc secrets plugin impl type fakeGRPCSecretsPlugin struct { kv map[Key]string diff --git a/pkg/services/secrets/manager/helpers.go b/pkg/services/secrets/manager/helpers.go index aacbb636e13..cc1df3e9a07 100644 --- a/pkg/services/secrets/manager/helpers.go +++ b/pkg/services/secrets/manager/helpers.go @@ -23,7 +23,7 @@ func SetupDisabledTestService(tb testing.TB, store secrets.Store) *SecretsServic return setupTestService(tb, store, featuremgmt.WithFeatures(featuremgmt.FlagDisableEnvelopeEncryption)) } -func setupTestService(tb testing.TB, store secrets.Store, features *featuremgmt.FeatureManager) *SecretsService { +func setupTestService(tb testing.TB, store secrets.Store, features featuremgmt.FeatureToggles) *SecretsService { tb.Helper() defaultKey := "SdlklWklckeLS" if len(setting.SecretKey) > 0 { diff --git a/pkg/services/serviceaccounts/extsvcaccounts/service.go b/pkg/services/serviceaccounts/extsvcaccounts/service.go index 84c984a0ac3..8b71b6e140e 100644 --- a/pkg/services/serviceaccounts/extsvcaccounts/service.go +++ b/pkg/services/serviceaccounts/extsvcaccounts/service.go @@ -26,7 +26,7 @@ import ( type ExtSvcAccountsService struct { acSvc ac.Service - features *featuremgmt.FeatureManager + features featuremgmt.FeatureToggles logger log.Logger metrics *metrics saSvc sa.Service diff --git a/pkg/services/serviceaccounts/extsvcaccounts/service_test.go b/pkg/services/serviceaccounts/extsvcaccounts/service_test.go index ab0c14c0aef..1624c71ed82 100644 --- a/pkg/services/serviceaccounts/extsvcaccounts/service_test.go +++ b/pkg/services/serviceaccounts/extsvcaccounts/service_test.go @@ -4,6 +4,9 @@ import ( "context" "testing" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + "github.com/grafana/grafana/pkg/infra/localcache" "github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/infra/tracing" @@ -18,8 +21,6 @@ import ( sa "github.com/grafana/grafana/pkg/services/serviceaccounts" "github.com/grafana/grafana/pkg/services/serviceaccounts/tests" "github.com/grafana/grafana/pkg/setting" - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/require" ) type TestEnv struct { diff --git a/pkg/services/sqlstore/permissions/dashboard_test.go b/pkg/services/sqlstore/permissions/dashboard_test.go index e6636b59e23..a21b109ccfa 100644 --- a/pkg/services/sqlstore/permissions/dashboard_test.go +++ b/pkg/services/sqlstore/permissions/dashboard_test.go @@ -195,7 +195,7 @@ func TestIntegration_DashboardPermissionFilter(t *testing.T) { usr := &user.SignedInUser{OrgID: 1, OrgRole: org.RoleViewer, Permissions: map[int64]map[string][]string{1: accesscontrol.GroupScopesByAction(tt.permissions)}} - for _, features := range []*featuremgmt.FeatureManager{featuremgmt.WithFeatures(), featuremgmt.WithFeatures(featuremgmt.FlagPermissionsFilterRemoveSubquery)} { + for _, features := range []featuremgmt.FeatureToggles{featuremgmt.WithFeatures(), featuremgmt.WithFeatures(featuremgmt.FlagPermissionsFilterRemoveSubquery)} { m := features.GetEnabled(context.Background()) keys := make([]string, 0, len(m)) for k := range m { @@ -394,7 +394,7 @@ func TestIntegration_DashboardPermissionFilter_WithSelfContainedPermissions(t *t usr := &user.SignedInUser{OrgID: 1, OrgRole: org.RoleViewer, AuthenticatedBy: login.ExtendedJWTModule, Permissions: map[int64]map[string][]string{1: accesscontrol.GroupScopesByAction(tt.signedInUserPermissions)}} - for _, features := range []*featuremgmt.FeatureManager{featuremgmt.WithFeatures(), featuremgmt.WithFeatures(featuremgmt.FlagPermissionsFilterRemoveSubquery)} { + for _, features := range []featuremgmt.FeatureToggles{featuremgmt.WithFeatures(), featuremgmt.WithFeatures(featuremgmt.FlagPermissionsFilterRemoveSubquery)} { m := features.GetEnabled(context.Background()) keys := make([]string, 0, len(m)) for k := range m { @@ -545,7 +545,7 @@ func TestIntegration_DashboardNestedPermissionFilter(t *testing.T) { }) usr := &user.SignedInUser{OrgID: orgID, OrgRole: org.RoleViewer, Permissions: map[int64]map[string][]string{orgID: accesscontrol.GroupScopesByAction(tc.permissions)}} - for _, features := range []*featuremgmt.FeatureManager{featuremgmt.WithFeatures(tc.features...), featuremgmt.WithFeatures(append(tc.features, featuremgmt.FlagPermissionsFilterRemoveSubquery)...)} { + for _, features := range []featuremgmt.FeatureToggles{featuremgmt.WithFeatures(tc.features...), featuremgmt.WithFeatures(append(tc.features, featuremgmt.FlagPermissionsFilterRemoveSubquery)...)} { m := features.GetEnabled(context.Background()) keys := make([]string, 0, len(m)) for k := range m { @@ -716,7 +716,7 @@ func TestIntegration_DashboardNestedPermissionFilter_WithSelfContainedPermission }), }, } - for _, features := range []*featuremgmt.FeatureManager{featuremgmt.WithFeatures(tc.features...), featuremgmt.WithFeatures(append(tc.features, featuremgmt.FlagPermissionsFilterRemoveSubquery)...)} { + for _, features := range []featuremgmt.FeatureToggles{featuremgmt.WithFeatures(tc.features...), featuremgmt.WithFeatures(append(tc.features, featuremgmt.FlagPermissionsFilterRemoveSubquery)...)} { m := features.GetEnabled(context.Background()) keys := make([]string, 0, len(m)) for k := range m { diff --git a/pkg/services/ssosettings/ssosettingsimpl/service.go b/pkg/services/ssosettings/ssosettingsimpl/service.go index 6e3b50c80a1..adfbe8969bc 100644 --- a/pkg/services/ssosettings/ssosettingsimpl/service.go +++ b/pkg/services/ssosettings/ssosettingsimpl/service.go @@ -34,7 +34,7 @@ type SSOSettingsService struct { } func ProvideService(cfg *setting.Cfg, sqlStore db.DB, ac ac.AccessControl, - routeRegister routing.RouteRegister, features *featuremgmt.FeatureManager, + routeRegister routing.RouteRegister, features featuremgmt.FeatureToggles, secrets secrets.Service) *SSOSettingsService { strategies := []ssosettings.FallbackStrategy{ strategies.NewOAuthStrategy(cfg), diff --git a/pkg/tsdb/influxdb/mocks_test.go b/pkg/tsdb/influxdb/mocks_test.go index 8b99d8ef842..c08090bb747 100644 --- a/pkg/tsdb/influxdb/mocks_test.go +++ b/pkg/tsdb/influxdb/mocks_test.go @@ -118,22 +118,8 @@ func GetMockService(version string, rt RoundTripper) *Service { version: version, fakeRoundTripper: rt, }, - features: &fakeFeatureToggles{ - flags: map[string]bool{ - featuremgmt.FlagInfluxqlStreamingParser: false, - }, - }, - } -} - -type fakeFeatureToggles struct { - flags map[string]bool -} - -func (f *fakeFeatureToggles) IsEnabledGlobally(flag string) bool { - return f.flags[flag] -} -func (f *fakeFeatureToggles) IsEnabled(ctx context.Context, flag string) bool { - return f.flags[flag] + // featuremgmt.FlagInfluxqlStreamingParser: false + features: featuremgmt.WithFeatures(), + } }