From 7a7d6d0c2de258f535e1b0a08df4f5340c0483b5 Mon Sep 17 00:00:00 2001 From: Ryan McKinley Date: Wed, 27 Nov 2024 09:29:31 +0300 Subject: [PATCH] POC/Provisioning: Use a single feature toggle to turn on required APIs (#97075) --- .../apis/dashboard/v0alpha1/register.go | 4 +++- pkg/registry/apis/folders/register.go | 9 ++++++--- pkg/registry/apis/provisioning/register.go | 3 ++- pkg/services/navtree/navtreeimpl/admin.go | 16 +++++++++------- .../app/features/provisioning/utils/routes.ts | 17 ++++++++++++----- 5 files changed, 32 insertions(+), 17 deletions(-) diff --git a/pkg/registry/apis/dashboard/v0alpha1/register.go b/pkg/registry/apis/dashboard/v0alpha1/register.go index 164b4eeac45..102723959e1 100644 --- a/pkg/registry/apis/dashboard/v0alpha1/register.go +++ b/pkg/registry/apis/dashboard/v0alpha1/register.go @@ -63,7 +63,9 @@ func RegisterAPIService(cfg *setting.Cfg, features featuremgmt.FeatureToggles, tracing *tracing.TracingService, unified resource.ResourceClient, ) *DashboardsAPIBuilder { - if !features.IsEnabledGlobally(featuremgmt.FlagGrafanaAPIServerWithExperimentalAPIs) && !features.IsEnabledGlobally(featuremgmt.FlagKubernetesDashboardsAPI) { + if !(features.IsEnabledGlobally(featuremgmt.FlagGrafanaAPIServerWithExperimentalAPIs) || + features.IsEnabledGlobally(featuremgmt.FlagKubernetesDashboardsAPI) || + features.IsEnabledGlobally(featuremgmt.FlagProvisioning)) { return nil // skip registration unless opting into experimental apis or dashboards in the k8s api } diff --git a/pkg/registry/apis/folders/register.go b/pkg/registry/apis/folders/register.go index 0da47483355..bd5d3456f66 100644 --- a/pkg/registry/apis/folders/register.go +++ b/pkg/registry/apis/folders/register.go @@ -5,7 +5,6 @@ import ( "errors" "slices" - grafanarest "github.com/grafana/grafana/pkg/apiserver/rest" "github.com/prometheus/client_golang/prometheus" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -17,6 +16,8 @@ import ( common "k8s.io/kube-openapi/pkg/common" "k8s.io/kube-openapi/pkg/spec3" + grafanarest "github.com/grafana/grafana/pkg/apiserver/rest" + "github.com/grafana/grafana/pkg/apimachinery/identity" "github.com/grafana/grafana/pkg/apimachinery/utils" "github.com/grafana/grafana/pkg/apis/folder/v0alpha1" @@ -55,8 +56,10 @@ func RegisterAPIService(cfg *setting.Cfg, accessControl accesscontrol.AccessControl, registerer prometheus.Registerer, ) *FolderAPIBuilder { - if !features.IsEnabledGlobally(featuremgmt.FlagKubernetesFolders) && !features.IsEnabledGlobally(featuremgmt.FlagGrafanaAPIServerTestingWithExperimentalAPIs) { - return nil // skip registration unless opting into Kubernetes folders or unless we want to customise registration when testing + if !(features.IsEnabledGlobally(featuremgmt.FlagGrafanaAPIServerWithExperimentalAPIs) || + features.IsEnabledGlobally(featuremgmt.FlagKubernetesFolders) || + features.IsEnabledGlobally(featuremgmt.FlagProvisioning)) { + return nil // skip registration unless opting into experimental apis or dashboards in the k8s api } builder := &FolderAPIBuilder{ diff --git a/pkg/registry/apis/provisioning/register.go b/pkg/registry/apis/provisioning/register.go index f1a403df746..8b4b5dffb4f 100644 --- a/pkg/registry/apis/provisioning/register.go +++ b/pkg/registry/apis/provisioning/register.go @@ -85,7 +85,8 @@ func RegisterAPIService( identities auth.BackgroundIdentityService, ghFactory github.ClientFactory, ) *ProvisioningAPIBuilder { - if !features.IsEnabledGlobally(featuremgmt.FlagProvisioning) && !features.IsEnabledGlobally(featuremgmt.FlagGrafanaAPIServerWithExperimentalAPIs) { + if !(features.IsEnabledGlobally(featuremgmt.FlagProvisioning) || + features.IsEnabledGlobally(featuremgmt.FlagGrafanaAPIServerWithExperimentalAPIs)) { return nil // skip registration unless opting into experimental apis OR the feature specifically } builder := NewProvisioningAPIBuilder(&repository.LocalFolderResolver{ diff --git a/pkg/services/navtree/navtreeimpl/admin.go b/pkg/services/navtree/navtreeimpl/admin.go index aa45c4fc4be..9a6f0f7b14f 100644 --- a/pkg/services/navtree/navtreeimpl/admin.go +++ b/pkg/services/navtree/navtreeimpl/admin.go @@ -70,13 +70,15 @@ func (s *ServiceImpl) getAdminNode(c *contextmodel.ReqContext) (*navtree.NavLink }) } - // TODO Add feature toggle / permissions check - generalNodeLinks = append(generalNodeLinks, &navtree.NavLink{ - Text: "Provisioning", - Id: "provisioning", - SubTitle: "Manage resources from remote repositories", - Url: s.cfg.AppSubURL + "/admin/provisioning", - }) + // TODO add permissions check + if s.features.IsEnabled(ctx, featuremgmt.FlagProvisioning) { + generalNodeLinks = append(generalNodeLinks, &navtree.NavLink{ + Text: "Provisioning", + Id: "provisioning", + SubTitle: "Manage resources from remote repositories", + Url: s.cfg.AppSubURL + "/admin/provisioning", + }) + } generalNode := &navtree.NavLink{ Text: "General", diff --git a/public/app/features/provisioning/utils/routes.ts b/public/app/features/provisioning/utils/routes.ts index 665c1eee395..7d0ab5977e0 100644 --- a/public/app/features/provisioning/utils/routes.ts +++ b/public/app/features/provisioning/utils/routes.ts @@ -1,35 +1,42 @@ +import { config } from '@grafana/runtime'; import { SafeDynamicImport } from 'app/core/components/DynamicImports/SafeDynamicImport'; import { RouteDescriptor } from 'app/core/navigation/types'; import { DashboardRoutes } from 'app/types'; +import { PROVISIONING_URL } from '../constants'; + export function getProvisioningRoutes(): RouteDescriptor[] { + if (!config.featureToggles.provisioning) { + return []; + } + return [ { - path: '/admin/provisioning', + path: PROVISIONING_URL, component: SafeDynamicImport( () => import(/* webpackChunkName: "RepositoryListPage"*/ 'app/features/provisioning/RepositoryListPage') ), }, { - path: '/admin/provisioning/new', + path: PROVISIONING_URL + '/new', component: SafeDynamicImport( () => import(/* webpackChunkName: "NewRepositoryPage"*/ 'app/features/provisioning/NewRepositoryPage') ), }, { - path: '/admin/provisioning/:name', + path: PROVISIONING_URL + '/:name', component: SafeDynamicImport( () => import(/* webpackChunkName: "RepositoryStatusPage"*/ 'app/features/provisioning/RepositoryStatusPage') ), }, { - path: '/admin/provisioning/:name/edit', + path: PROVISIONING_URL + '/:name/edit', component: SafeDynamicImport( () => import(/* webpackChunkName: "EditRepositoryPage"*/ 'app/features/provisioning/EditRepositoryPage') ), }, { - path: '/admin/provisioning/:slug/dashboard/preview/*', + path: PROVISIONING_URL + '/:slug/dashboard/preview/*', pageClass: 'page-dashboard', routeName: DashboardRoutes.Provisioning, component: SafeDynamicImport(