diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 12ba8f3cf58..905cfad2951 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -870,6 +870,7 @@ playwright.storybook.config.ts @grafana/grafana-frontend-platform /public/app/core/utils/accessControl.ts @grafana/identity-access-team /public/app/core/utils/applyStateChanges.ts @grafana/dashboards-squad /public/app/core/utils/arrayMove.ts @grafana/grafana-frontend-platform +/public/app/core/utils/isFrontendService.ts @grafana/grafana-frontend-platform /public/app/core/utils/auth.ts @grafana/identity-access-team /public/app/core/utils/browser* @grafana/grafana-frontend-platform /public/app/core/utils/colors.ts @grafana/grafana-frontend-platform diff --git a/devenv/frontend-service/docker-compose.yaml b/devenv/frontend-service/docker-compose.yaml index 727a36a3b66..fd744e29ccd 100644 --- a/devenv/frontend-service/docker-compose.yaml +++ b/devenv/frontend-service/docker-compose.yaml @@ -35,7 +35,7 @@ services: GF_DEFAULT_APP_MODE: development GF_PANELS_ENABLE_ALPHA: true GF_SERVER_CDN_URL: http://localhost:3010 - GF_FEATURE_TOGGLES_ENABLE: multiTenantFrontend enableNativeHTTPHistogram + GF_FEATURE_TOGGLES_ENABLE: enableNativeHTTPHistogram GF_DATABASE_URL: postgres://grafana:grafana@postgres:5432/grafana GF_SERVER_ROUTER_LOGGING: true GF_LOG_LEVEL: info diff --git a/packages/grafana-data/src/types/config.ts b/packages/grafana-data/src/types/config.ts index 485b1ec4294..29079be8bd8 100644 --- a/packages/grafana-data/src/types/config.ts +++ b/packages/grafana-data/src/types/config.ts @@ -195,6 +195,9 @@ export interface BootData { light: string; dark: string; }; + + /** @deprecated Internal Grafana usage only. This property will be removed at any time. */ + _femt?: boolean; } /** diff --git a/packages/grafana-data/src/types/featureToggles.gen.ts b/packages/grafana-data/src/types/featureToggles.gen.ts index 614feba90a6..d4c846c2f53 100644 --- a/packages/grafana-data/src/types/featureToggles.gen.ts +++ b/packages/grafana-data/src/types/featureToggles.gen.ts @@ -965,10 +965,6 @@ export interface FeatureToggles { */ pluginsAutoUpdate?: boolean; /** - * Register MT frontend - */ - multiTenantFrontend?: boolean; - /** * Enables the alerting list view v2 preview toggle */ alertingListViewV2PreviewToggle?: boolean; diff --git a/pkg/api/api.go b/pkg/api/api.go index a1ba8591044..d9689f92eb4 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -84,10 +84,8 @@ func (hs *HTTPServer) registerRoutes() { r.Get("/login", hs.LoginView) r.Get("/invite/:code", hs.Index) - if hs.Features.IsEnabledGlobally(featuremgmt.FlagMultiTenantFrontend) { - // Temporarily expose the full bootdata via API - r.Get("/bootdata", reqNoAuth, hs.GetBootdata) - } + // Temporary MT-frontend config endpoint + r.Get("/bootdata", reqNoAuth, hs.GetBootdata) // authed views r.Get("/", reqSignedIn, hs.Index) diff --git a/pkg/api/frontendsettings.go b/pkg/api/frontendsettings.go index c7ee1818700..7b8230df5a3 100644 --- a/pkg/api/frontendsettings.go +++ b/pkg/api/frontendsettings.go @@ -32,9 +32,12 @@ import ( // NOTE: this should not be added to the public API docs, and is useful for a transition // towards a fully static index.html -- this will likely be replaced with multiple calls func (hs *HTTPServer) GetBootdata(c *contextmodel.ReqContext) { + c, span := hs.injectSpan(c, "api.GetBootdata") + defer span.End() + data, err := hs.setIndexViewData(c) if err != nil { - c.Handle(hs.Cfg, http.StatusInternalServerError, "Failed to get settings", err) + c.JsonApiErr(http.StatusInternalServerError, "Failed to get settings", err) return } c.JSON(http.StatusOK, data) diff --git a/pkg/services/featuremgmt/registry.go b/pkg/services/featuremgmt/registry.go index a80b38250c6..4a5d9f8a704 100644 --- a/pkg/services/featuremgmt/registry.go +++ b/pkg/services/featuremgmt/registry.go @@ -1664,13 +1664,6 @@ var ( FrontendOnly: false, Owner: grafanaPluginsPlatformSquad, }, - { - Name: "multiTenantFrontend", - Description: "Register MT frontend", - Stage: FeatureStageExperimental, - FrontendOnly: false, - Owner: grafanaFrontendPlatformSquad, - }, { Name: "alertingListViewV2PreviewToggle", Description: "Enables the alerting list view v2 preview toggle", diff --git a/pkg/services/featuremgmt/toggles_gen.csv b/pkg/services/featuremgmt/toggles_gen.csv index 2c1bae54ff0..479533a14b8 100644 --- a/pkg/services/featuremgmt/toggles_gen.csv +++ b/pkg/services/featuremgmt/toggles_gen.csv @@ -216,7 +216,6 @@ grafanaAssistantInProfilesDrilldown,GA,@grafana/observability-traces-and-profili postgresDSUsePGX,experimental,@grafana/oss-big-tent,false,false,false tempoAlerting,experimental,@grafana/observability-traces-and-profiling,false,false,true pluginsAutoUpdate,experimental,@grafana/plugins-platform-backend,false,false,false -multiTenantFrontend,experimental,@grafana/grafana-frontend-platform,false,false,false alertingListViewV2PreviewToggle,privatePreview,@grafana/alerting-squad,false,false,true alertRuleUseFiredAtForStartsAt,experimental,@grafana/alerting-squad,false,false,false alertingBulkActionsInUI,GA,@grafana/alerting-squad,false,false,true diff --git a/pkg/services/featuremgmt/toggles_gen.go b/pkg/services/featuremgmt/toggles_gen.go index 91761a72af7..2d381369453 100644 --- a/pkg/services/featuremgmt/toggles_gen.go +++ b/pkg/services/featuremgmt/toggles_gen.go @@ -875,10 +875,6 @@ const ( // Enables auto-updating of users installed plugins FlagPluginsAutoUpdate = "pluginsAutoUpdate" - // FlagMultiTenantFrontend - // Register MT frontend - FlagMultiTenantFrontend = "multiTenantFrontend" - // FlagAlertingListViewV2PreviewToggle // Enables the alerting list view v2 preview toggle FlagAlertingListViewV2PreviewToggle = "alertingListViewV2PreviewToggle" diff --git a/pkg/services/featuremgmt/toggles_gen.json b/pkg/services/featuremgmt/toggles_gen.json index 193ef690009..c19449bd9f0 100644 --- a/pkg/services/featuremgmt/toggles_gen.json +++ b/pkg/services/featuremgmt/toggles_gen.json @@ -2229,7 +2229,8 @@ "metadata": { "name": "multiTenantFrontend", "resourceVersion": "1753448760331", - "creationTimestamp": "2025-04-25T09:24:25Z" + "creationTimestamp": "2025-04-25T09:24:25Z", + "deletionTimestamp": "2025-09-08T17:06:39Z" }, "spec": { "description": "Register MT frontend", diff --git a/pkg/services/frontend/index.html b/pkg/services/frontend/index.html index 276cb4494b4..10cc7234b78 100644 --- a/pkg/services/frontend/index.html +++ b/pkg/services/frontend/index.html @@ -252,7 +252,7 @@ const rawBootData = await loadBootData(); window.grafanaBootData = { - _femt: true, + _femt: true, // isFrontendService() needs this ...rawBootData, } diff --git a/pkg/tests/apis/preferences/preferences_test.go b/pkg/tests/apis/preferences/preferences_test.go index 6579384c539..04152b4026a 100644 --- a/pkg/tests/apis/preferences/preferences_test.go +++ b/pkg/tests/apis/preferences/preferences_test.go @@ -30,7 +30,6 @@ func TestIntegrationPreferences(t *testing.T) { DisableAnonymous: true, EnableFeatureToggles: []string{ featuremgmt.FlagGrafanaAPIServerWithExperimentalAPIs, - featuremgmt.FlagMultiTenantFrontend, // So we can compare to boot-data preferences }, }) diff --git a/public/app/core/components/AppChrome/TopBar/SignInLink.test.tsx b/public/app/core/components/AppChrome/TopBar/SignInLink.test.tsx index c6903685aef..90e5360c136 100644 --- a/public/app/core/components/AppChrome/TopBar/SignInLink.test.tsx +++ b/public/app/core/components/AppChrome/TopBar/SignInLink.test.tsx @@ -22,9 +22,9 @@ describe('SignInLink', () => { expect(link).toHaveAttribute('target', '_self'); }); - describe('with multiTenantFrontend toggle enabled', () => { + describe('with frontend-service enabled', () => { beforeAll(() => { - config.featureToggles.multiTenantFrontend = true; + config.bootData._femt = true; }); it('should render a link to the login page', () => { diff --git a/public/app/core/components/AppChrome/TopBar/SignInLink.tsx b/public/app/core/components/AppChrome/TopBar/SignInLink.tsx index 7c93f089741..13149e8e381 100644 --- a/public/app/core/components/AppChrome/TopBar/SignInLink.tsx +++ b/public/app/core/components/AppChrome/TopBar/SignInLink.tsx @@ -4,12 +4,12 @@ import { useLocation } from 'react-router-dom-v5-compat'; import { GrafanaTheme2, locationUtil, textUtil } from '@grafana/data'; import { Trans } from '@grafana/i18n'; -import { config } from '@grafana/runtime'; import { useStyles2 } from '@grafana/ui'; import { contextSrv } from 'app/core/services/context_srv'; +import { isFrontendService } from 'app/core/utils/isFrontendService'; export function SignInLink() { - const femt = Boolean(config.featureToggles.multiTenantFrontend); + const femt = isFrontendService(); const location = useLocation(); const styles = useStyles2(getStyles); let loginUrl = femt diff --git a/public/app/core/navigation/GrafanaRoute.tsx b/public/app/core/navigation/GrafanaRoute.tsx index c5c751366dc..10cef729d3f 100644 --- a/public/app/core/navigation/GrafanaRoute.tsx +++ b/public/app/core/navigation/GrafanaRoute.tsx @@ -3,6 +3,7 @@ import { Navigate, useLocation } from 'react-router-dom-v5-compat'; import { config, locationSearchToObject, navigationLogger, reportPageview } from '@grafana/runtime'; import { ErrorBoundary } from '@grafana/ui'; +import { isFrontendService } from 'app/core/utils/isFrontendService'; import { useGrafana } from '../context/GrafanaContext'; import { contextSrv } from '../services/context_srv'; @@ -64,7 +65,7 @@ export function GrafanaRouteWrapper({ route }: Pick) { const location = useLocation(); // Perform login check in the frontend now - if (config.featureToggles.multiTenantFrontend) { + if (isFrontendService()) { const routeRequiresSignin = !route.allowAnonymous && !config.anonymousEnabled; if (routeRequiresSignin && !contextSrv.isSignedIn) { contextSrv.setRedirectToUrl(); diff --git a/public/app/core/navigation/types.ts b/public/app/core/navigation/types.ts index 8fafbfa2a8b..757eeefb725 100644 --- a/public/app/core/navigation/types.ts +++ b/public/app/core/navigation/types.ts @@ -23,7 +23,7 @@ export interface RouteDescriptor { /** * Allow the route to be access by anonymous users. - * Currently only used if the `multiTenantFrontend` feature toggle is enabled. + * Currently only used when using the frontend-service. */ allowAnonymous?: boolean; } diff --git a/public/app/core/utils/isFrontendService.ts b/public/app/core/utils/isFrontendService.ts new file mode 100644 index 00000000000..0d1cb690ac4 --- /dev/null +++ b/public/app/core/utils/isFrontendService.ts @@ -0,0 +1,9 @@ +import { config } from '@grafana/runtime'; + +/** + * Returns true if the current instance is using the frontend-service. + * @internal + */ +export function isFrontendService() { + return config.bootData._femt; +}