chore : Deprecating FeatureToggles.IsEnabled (#113062)

* Deprecating features.IsEnabled

* add one more nolint

* add one more nolint

* Give better hints to devs in the deprecation message of IsEnabledGlobally

* adding more doc strings

* fix linter after rebase

* Extend deprecation message
This commit is contained in:
Denis Vodopianov
2025-11-21 18:43:42 +01:00
committed by GitHub
parent 43217025cf
commit 0e460a267e
34 changed files with 91 additions and 17 deletions
+2
View File
@@ -313,6 +313,7 @@ func (hs *HTTPServer) declareFixedRoles() error {
Grants: []string{string(org.RoleEditor)},
}
//nolint:staticcheck // not yet migrated to OpenFeature
if hs.Features.IsEnabled(context.Background(), featuremgmt.FlagAnnotationPermissionUpdate) {
// Keeping the name to avoid breaking changes (for users who have assigned this role to grant permissions on organization annotations)
annotationsReaderRole = ac.RoleRegistration{
@@ -619,6 +620,7 @@ func (hs *HTTPServer) declareFixedRoles() error {
libraryPanelsReaderRole, libraryPanelsWriterRole, libraryPanelsGeneralReaderRole, libraryPanelsGeneralWriterRole,
snapshotsCreatorRole, snapshotsDeleterRole, snapshotsReaderRole}
//nolint:staticcheck // not yet migrated to OpenFeature
if hs.Features.IsEnabled(context.Background(), featuremgmt.FlagAnnotationPermissionUpdate) {
allAnnotationsReaderRole := ac.RoleRegistration{
Role: ac.RoleDTO{
+9
View File
@@ -126,6 +126,7 @@ func (hs *HTTPServer) PostAnnotation(c *contextmodel.ReqContext) response.Respon
}
if canSave, err := hs.canCreateAnnotation(c, cmd.DashboardUID); err != nil || !canSave {
//nolint:staticcheck // not yet migrated to OpenFeature
if !hs.Features.IsEnabled(c.Req.Context(), featuremgmt.FlagAnnotationPermissionUpdate) {
return dashboardGuardianResponse(err)
} else if err != nil {
@@ -271,6 +272,7 @@ func (hs *HTTPServer) UpdateAnnotation(c *contextmodel.ReqContext) response.Resp
return resp
}
//nolint:staticcheck // not yet migrated to OpenFeature
if !hs.Features.IsEnabled(c.Req.Context(), featuremgmt.FlagAnnotationPermissionUpdate) {
if canSave, err := hs.canSaveAnnotation(c, hs.AccessControl, annotation); err != nil || !canSave {
return dashboardGuardianResponse(err)
@@ -329,6 +331,7 @@ func (hs *HTTPServer) PatchAnnotation(c *contextmodel.ReqContext) response.Respo
return resp
}
//nolint:staticcheck // not yet migrated to OpenFeature
if !hs.Features.IsEnabled(c.Req.Context(), featuremgmt.FlagAnnotationPermissionUpdate) {
if canSave, err := hs.canSaveAnnotation(c, hs.AccessControl, annotation); err != nil || !canSave {
return dashboardGuardianResponse(err)
@@ -439,6 +442,7 @@ func (hs *HTTPServer) MassDeleteAnnotations(c *contextmodel.ReqContext) response
canSave, err := hs.canMassDeleteAnnotations(c, dashboardUID)
if err != nil || !canSave {
//nolint:staticcheck // not yet migrated to OpenFeature
if !hs.Features.IsEnabled(c.Req.Context(), featuremgmt.FlagAnnotationPermissionUpdate) {
return dashboardGuardianResponse(err)
} else if err != nil {
@@ -500,6 +504,7 @@ func (hs *HTTPServer) DeleteAnnotationByID(c *contextmodel.ReqContext) response.
return response.Error(http.StatusBadRequest, "annotationId is invalid", err)
}
//nolint:staticcheck // not yet migrated to OpenFeature
if !hs.Features.IsEnabled(c.Req.Context(), featuremgmt.FlagAnnotationPermissionUpdate) {
annotation, resp := findAnnotationByID(c.Req.Context(), hs.annotationsRepo, annotationID, c.SignedInUser)
if resp != nil {
@@ -610,6 +615,7 @@ func AnnotationTypeScopeResolver(annotationsRepo annotations.Repository, feature
},
}
//nolint:staticcheck // not yet migrated to OpenFeature
if features.IsEnabled(ctx, featuremgmt.FlagAnnotationPermissionUpdate) {
tempUser = &user.SignedInUser{
OrgID: orgID,
@@ -626,6 +632,7 @@ func AnnotationTypeScopeResolver(annotationsRepo annotations.Repository, feature
return nil, errors.New("could not resolve annotation type")
}
//nolint:staticcheck // not yet migrated to OpenFeature
if !features.IsEnabled(ctx, featuremgmt.FlagAnnotationPermissionUpdate) {
switch annotation.GetType() {
case annotations.Organization:
@@ -662,6 +669,7 @@ func AnnotationTypeScopeResolver(annotationsRepo annotations.Repository, feature
}
func (hs *HTTPServer) canCreateAnnotation(c *contextmodel.ReqContext, dashboardUID string) (bool, error) {
//nolint:staticcheck // not yet migrated to OpenFeature
if hs.Features.IsEnabled(c.Req.Context(), featuremgmt.FlagAnnotationPermissionUpdate) {
if dashboardUID != "" {
evaluator := accesscontrol.EvalPermission(accesscontrol.ActionAnnotationsCreate, dashboards.ScopeDashboardsProvider.GetResourceScopeUID(dashboardUID))
@@ -686,6 +694,7 @@ func (hs *HTTPServer) canCreateAnnotation(c *contextmodel.ReqContext, dashboardU
}
func (hs *HTTPServer) canMassDeleteAnnotations(c *contextmodel.ReqContext, dashboardUID string) (bool, error) {
//nolint:staticcheck // not yet migrated to OpenFeature
if hs.Features.IsEnabled(c.Req.Context(), featuremgmt.FlagAnnotationPermissionUpdate) {
if dashboardUID == "" {
evaluator := accesscontrol.EvalPermission(accesscontrol.ActionAnnotationsDelete, accesscontrol.ScopeAnnotationsTypeOrganization)
+1
View File
@@ -166,6 +166,7 @@ func (hs *HTTPServer) GetDashboard(c *contextmodel.ReqContext) response.Response
}
annotationPermissions := &dashboardsV1.AnnotationPermission{}
//nolint:staticcheck // not yet migrated to OpenFeature
if hs.Features.IsEnabled(ctx, featuremgmt.FlagAnnotationPermissionUpdate) {
hs.getAnnotationPermissionsByScope(c, &annotationPermissions.Dashboard, dashboards.ScopeDashboardsProvider.GetResourceScopeUID(dash.UID))
} else {
+4
View File
@@ -150,6 +150,7 @@ func (hs *HTTPServer) getFrontendSettings(c *contextmodel.ReqContext) (*dtos.Fro
continue
}
//nolint:staticcheck // not yet migrated to OpenFeature
if panel.ID == "datagrid" && !hs.Features.IsEnabled(c.Req.Context(), featuremgmt.FlagEnableDatagridEditing) {
continue
}
@@ -190,6 +191,7 @@ func (hs *HTTPServer) getFrontendSettings(c *contextmodel.ReqContext) (*dtos.Fro
hasAccess := accesscontrol.HasAccess(hs.AccessControl, c)
trustedTypesDefaultPolicyEnabled := (hs.Cfg.CSPEnabled && strings.Contains(hs.Cfg.CSPTemplate, "require-trusted-types-for")) || (hs.Cfg.CSPReportOnlyEnabled && strings.Contains(hs.Cfg.CSPReportOnlyTemplate, "require-trusted-types-for"))
//nolint:staticcheck // not yet migrated to OpenFeature
isCloudMigrationTarget := hs.Features.IsEnabled(c.Req.Context(), featuremgmt.FlagOnPremToCloudMigrations) && hs.Cfg.CloudMigration.IsTarget
featureToggles := hs.Features.GetEnabled(c.Req.Context())
// this is needed for backwards compatibility with external plugins
@@ -406,6 +408,7 @@ func (hs *HTTPServer) getFrontendSettings(c *contextmodel.ReqContext) (*dtos.Fro
DisableSignoutMenu: hs.Cfg.DisableSignoutMenu,
}
//nolint:staticcheck // not yet migrated to OpenFeature
if hs.Cfg.PasswordlessMagicLinkAuth.Enabled && hs.Features.IsEnabled(c.Req.Context(), featuremgmt.FlagPasswordlessMagicLinkAuthentication) {
hasEnabledProviders := hs.samlEnabled() || hs.authnService.IsClientEnabled(authn.ClientLDAP)
@@ -444,6 +447,7 @@ func (hs *HTTPServer) getFrontendSettings(c *contextmodel.ReqContext) (*dtos.Fro
frontendSettings.Namespace = hs.namespacer(c.OrgID)
// experimental scope features
//nolint:staticcheck // not yet migrated to OpenFeature
if hs.Features.IsEnabled(c.Req.Context(), featuremgmt.FlagScopeFilters) {
frontendSettings.ListScopesEndpoint = hs.Cfg.ScopesListScopesURL
frontendSettings.ListDashboardScopesEndpoint = hs.Cfg.ScopesListDashboardsURL
+2
View File
@@ -62,6 +62,7 @@ func (hs *HTTPServer) setIndexViewData(c *contextmodel.ReqContext) (*dtos.IndexV
return nil, err
}
//nolint:staticcheck // not yet migrated to OpenFeature
if hs.Features.IsEnabled(c.Req.Context(), featuremgmt.FlagIndividualCookiePreferences) {
if !prefs.Cookies("analytics") {
settings.GoogleAnalytics4Id = ""
@@ -94,6 +95,7 @@ func (hs *HTTPServer) setIndexViewData(c *contextmodel.ReqContext) (*dtos.IndexV
}
var regionalFormat string
//nolint:staticcheck // not yet migrated to OpenFeature
if hs.Features.IsEnabled(c.Req.Context(), featuremgmt.FlagLocaleFormatPreference) {
regionalFormat = "en"
+1
View File
@@ -361,6 +361,7 @@ func (hs *HTTPServer) RedirectResponseWithError(c *contextmodel.ReqContext, err
func (hs *HTTPServer) redirectURLWithErrorCookie(c *contextmodel.ReqContext, err error) string {
setCookie := true
//nolint:staticcheck // not yet migrated to OpenFeature
if hs.Features.IsEnabled(c.Req.Context(), featuremgmt.FlagIndividualCookiePreferences) {
var userID int64
if c.SignedInUser != nil && !c.IsNil() {
+1
View File
@@ -81,6 +81,7 @@ func (proxy *PluginProxy) HandleRequest() {
hasSlash := strings.HasSuffix(proxy.proxyPath, "/")
proxy.proxyPath = path
//nolint:staticcheck // not yet migrated to OpenFeature
if hasSlash && !strings.HasSuffix(path, "/") && proxy.features.IsEnabled(proxy.ctx.Req.Context(), featuremgmt.FlagPluginProxyPreserveTrailingSlash) {
proxy.proxyPath += "/"
}
+2
View File
@@ -144,6 +144,7 @@ func (hs *HTTPServer) GetPluginList(c *contextmodel.ReqContext) response.Respons
AngularDetected: pluginDef.Angular.Detected,
}
//nolint:staticcheck // not yet migrated to OpenFeature
if hs.Cfg.ManagedServiceAccountsEnabled && hs.Features.IsEnabled(c.Req.Context(), featuremgmt.FlagExternalServiceAccounts) {
listItem.IAM = pluginDef.IAM
}
@@ -490,6 +491,7 @@ func (hs *HTTPServer) InstallPlugin(c *contextmodel.ReqContext) response.Respons
return response.ErrOrFallback(http.StatusInternalServerError, "Failed to install plugin", err)
}
//nolint:staticcheck // not yet migrated to OpenFeature
if hs.Cfg.ManagedServiceAccountsEnabled && hs.Features.IsEnabled(c.Req.Context(), featuremgmt.FlagExternalServiceAccounts) {
// This is a non-blocking function that verifies that the installer has
// the permissions that the plugin requests to have on Grafana.