From c7a7f7dce5d93dc5044c4be140433ee2d6150fb9 Mon Sep 17 00:00:00 2001 From: Marcus Andersson Date: Tue, 5 Nov 2024 16:55:10 +0100 Subject: [PATCH] PluginExtensions: Made it possible to enable extensions admin page in non-development environments (#95820) * Added feature flag for toggling extensions admin page. * fixed typo. * require restart --------- Co-authored-by: Erik Sundell --- .../configure-grafana/feature-toggles/index.md | 1 + .../grafana-data/src/types/featureToggles.gen.ts | 1 + pkg/services/featuremgmt/registry.go | 7 +++++++ pkg/services/featuremgmt/toggles_gen.csv | 1 + pkg/services/featuremgmt/toggles_gen.go | 4 ++++ pkg/services/featuremgmt/toggles_gen.json | 16 ++++++++++++++++ pkg/services/navtree/navtreeimpl/admin.go | 2 +- public/app/routes/routes.tsx | 14 +++++++++----- 8 files changed, 40 insertions(+), 6 deletions(-) diff --git a/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md b/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md index ab9db38b18d..e657ac6a741 100644 --- a/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md +++ b/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md @@ -217,6 +217,7 @@ Experimental features might be changed or removed without prior notice. | `prometheusUsesCombobox` | Use new combobox component for Prometheus query editor | | `dashboardSchemaV2` | Enables the new dashboard schema version 2, implementing changes necessary for dynamic dashboards and dashboards as code. | | `playlistsWatcher` | Enables experimental watcher for playlists | +| `enableExtensionsAdminPage` | Enables the extension admin page regardless of development mode | ## Development feature toggles diff --git a/packages/grafana-data/src/types/featureToggles.gen.ts b/packages/grafana-data/src/types/featureToggles.gen.ts index e1dc98f8c4d..5659ac3d70a 100644 --- a/packages/grafana-data/src/types/featureToggles.gen.ts +++ b/packages/grafana-data/src/types/featureToggles.gen.ts @@ -228,4 +228,5 @@ export interface FeatureToggles { azureMonitorDisableLogLimit?: boolean; dashboardSchemaV2?: boolean; playlistsWatcher?: boolean; + enableExtensionsAdminPage?: boolean; } diff --git a/pkg/services/featuremgmt/registry.go b/pkg/services/featuremgmt/registry.go index ef8f5f1c0c6..cfcc24edd7e 100644 --- a/pkg/services/featuremgmt/registry.go +++ b/pkg/services/featuremgmt/registry.go @@ -1570,6 +1570,13 @@ var ( Owner: grafanaAppPlatformSquad, RequiresRestart: true, }, + { + Name: "enableExtensionsAdminPage", + Description: "Enables the extension admin page regardless of development mode", + Stage: FeatureStageExperimental, + Owner: grafanaPluginsPlatformSquad, + RequiresRestart: true, + }, } ) diff --git a/pkg/services/featuremgmt/toggles_gen.csv b/pkg/services/featuremgmt/toggles_gen.csv index f4ce89233c3..d9b8866677b 100644 --- a/pkg/services/featuremgmt/toggles_gen.csv +++ b/pkg/services/featuremgmt/toggles_gen.csv @@ -209,3 +209,4 @@ prometheusUsesCombobox,experimental,@grafana/observability-metrics,false,false,f azureMonitorDisableLogLimit,GA,@grafana/partner-datasources,false,false,false dashboardSchemaV2,experimental,@grafana/dashboards-squad,false,false,true playlistsWatcher,experimental,@grafana/grafana-app-platform-squad,false,true,false +enableExtensionsAdminPage,experimental,@grafana/plugins-platform-backend,false,true,false diff --git a/pkg/services/featuremgmt/toggles_gen.go b/pkg/services/featuremgmt/toggles_gen.go index 248b5c8004b..21a69174c78 100644 --- a/pkg/services/featuremgmt/toggles_gen.go +++ b/pkg/services/featuremgmt/toggles_gen.go @@ -846,4 +846,8 @@ const ( // FlagPlaylistsWatcher // Enables experimental watcher for playlists FlagPlaylistsWatcher = "playlistsWatcher" + + // FlagEnableExtensionsAdminPage + // Enables the extension admin page regardless of development mode + FlagEnableExtensionsAdminPage = "enableExtensionsAdminPage" ) diff --git a/pkg/services/featuremgmt/toggles_gen.json b/pkg/services/featuremgmt/toggles_gen.json index 09cf086e4a1..90efd2f74c8 100644 --- a/pkg/services/featuremgmt/toggles_gen.json +++ b/pkg/services/featuremgmt/toggles_gen.json @@ -1201,6 +1201,22 @@ "frontend": true } }, + { + "metadata": { + "name": "enableExtensionsAdminPage", + "resourceVersion": "1730819353237", + "creationTimestamp": "2024-11-05T09:18:42Z", + "annotations": { + "grafana.app/updatedTimestamp": "2024-11-05 15:09:13.237578 +0000 UTC" + } + }, + "spec": { + "description": "Enables the extension admin page regardless of development mode", + "stage": "experimental", + "codeowner": "@grafana/plugins-platform-backend", + "requiresRestart": true + } + }, { "metadata": { "name": "enableNativeHTTPHistogram", diff --git a/pkg/services/navtree/navtreeimpl/admin.go b/pkg/services/navtree/navtreeimpl/admin.go index 18a71f24dde..66f50147643 100644 --- a/pkg/services/navtree/navtreeimpl/admin.go +++ b/pkg/services/navtree/navtreeimpl/admin.go @@ -105,7 +105,7 @@ func (s *ServiceImpl) getAdminNode(c *contextmodel.ReqContext) (*navtree.NavLink }) } - if s.cfg.Env == setting.Dev { + if (s.cfg.Env == setting.Dev) || s.features.IsEnabled(ctx, featuremgmt.FlagEnableExtensionsAdminPage) && hasAccess(pluginaccesscontrol.AdminAccessEvaluator) { pluginsNodeLinks = append(pluginsNodeLinks, &navtree.NavLink{ Text: "Extensions", Icon: "plug", diff --git a/public/app/routes/routes.tsx b/public/app/routes/routes.tsx index dd1a0a4967a..a3a88ca83b8 100644 --- a/public/app/routes/routes.tsx +++ b/public/app/routes/routes.tsx @@ -203,11 +203,15 @@ export function getAppRoutes(): RouteDescriptor[] { { path: '/admin/extensions', navId: 'extensions', - component: isDevEnv - ? SafeDynamicImport( - () => import(/* webpackChunkName: "PluginExtensionsLog" */ 'app/features/plugins/extensions/logs/LogViewer') - ) - : () => , + roles: () => + contextSrv.evaluatePermission([AccessControlAction.PluginsInstall, AccessControlAction.PluginsWrite]), + component: + isDevEnv || config.featureToggles.enableExtensionsAdminPage + ? SafeDynamicImport( + () => + import(/* webpackChunkName: "PluginExtensionsLog" */ 'app/features/plugins/extensions/logs/LogViewer') + ) + : () => , }, { path: '/admin/access',