From d0a0a1f9e65eae0316a72272c00b1ff5c8a4b876 Mon Sep 17 00:00:00 2001 From: Mykola Harmash Date: Fri, 29 Sep 2023 11:27:19 +0200 Subject: [PATCH] [Infra IU] Disable Metrics Explorer for serverless (#167022) Closes #163282 ## Summary This PR: * Adds a `featureFlags.metricsExplorerEnabled` property to the Infra plugin config to enable and disable Metrics Explorer depending on the offering type * Prevents `MetricsExplorerViewsService` initialization for serveless based on the feature flag * Prevents creating Metrics Explorer frontend routes when in serverless * Prevents registration of the MetricsExplorerViews saved object when in serverless * Prevents initialization of the `metrics_explorer_views` API routes when in serverless **Trying to access Metrics Explorer in serverless** CleanShot 2023-09-22 at 12 59 35@2x **Trying to access views API** CleanShot 2023-09-22 at 13 00 00@2x **`infra/metrics_explorer` API still works as per ticket requirements** CleanShot 2023-09-22 at 13 00 06@2x ## How to test * Checkout locally * Enable Infra in `serverless.oblt.yml`: `xpack.infra.enabled: true` * Run Kibana in serverless mode * Try accessing `/app/metrics/explorer` route and make sure it's not available * Make sure other Infra routes (`/app/metrics/inventory` and `/app/metrics/hosts`) still load as expected * In Kibana dev console make sure you get 404 for `GET kbn:/api/infra/metrics_explorer_views` * Also check that you don't see `metrics-explorer-view` saved object in the response for `GET kbn:/api/kibana/management/saved_objects/_allowed_types` * Run Kibana in non-serverless mode and make sure Metrics Explorer is accessible and works as usual --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../test_suites/core_plugins/rendering.ts | 5 ++ .../metrics_explorer_views/v1/common.ts | 3 +- .../infra/common/plugin_config_types.ts | 4 ++ .../plugins/infra/public/apps/metrics_app.tsx | 52 ++++++++++++------- .../containers/plugin_config_context.test.tsx | 32 ++++++++++++ .../containers/plugin_config_context.ts | 25 +++++++++ .../hooks/use_metrics_explorer_views.ts | 7 ++- .../infra/public/pages/metrics/index.tsx | 39 +++++++------- .../pages/metrics/metrics_explorer/index.tsx | 1 + x-pack/plugins/infra/public/plugin.ts | 31 +++++++---- x-pack/plugins/infra/public/types.ts | 2 +- .../framework/kibana_framework_adapter.ts | 2 + .../metric_threshold_executor.test.ts | 3 ++ .../infra/server/lib/sources/sources.test.ts | 3 ++ x-pack/plugins/infra/server/plugin.ts | 24 ++++++--- .../create_metrics_explorer_view.ts | 12 +++++ .../delete_metrics_explorer_view.ts | 12 +++++ .../find_metrics_explorer_view.ts | 12 +++++ .../get_metrics_explorer_view.ts | 12 +++++ .../routes/metrics_explorer_views/index.ts | 4 ++ .../update_metrics_explorer_view.ts | 12 +++++ x-pack/plugins/infra/server/types.ts | 4 +- 22 files changed, 239 insertions(+), 62 deletions(-) create mode 100644 x-pack/plugins/infra/public/containers/plugin_config_context.test.tsx create mode 100644 x-pack/plugins/infra/public/containers/plugin_config_context.ts diff --git a/test/plugin_functional/test_suites/core_plugins/rendering.ts b/test/plugin_functional/test_suites/core_plugins/rendering.ts index ca639ed3272f..f54dcb6c13c6 100644 --- a/test/plugin_functional/test_suites/core_plugins/rendering.ts +++ b/test/plugin_functional/test_suites/core_plugins/rendering.ts @@ -250,6 +250,11 @@ export default function ({ getService }: PluginFunctionalProviderContext) { 'xpack.index_management.enableLegacyTemplates (any)', 'xpack.index_management.enableIndexStats (any)', 'xpack.infra.sources.default.fields.message (array)', + /** + * xpack.infra.featureFlags.metricsExplorerEnabled is conditional based on traditional/serverless offering + * and will resolve to (boolean) + */ + 'xpack.infra.featureFlags.metricsExplorerEnabled (any)', 'xpack.license_management.ui.enabled (boolean)', 'xpack.maps.preserveDrawingBuffer (boolean)', 'xpack.maps.showMapsInspectorAdapter (boolean)', diff --git a/x-pack/plugins/infra/common/http_api/metrics_explorer_views/v1/common.ts b/x-pack/plugins/infra/common/http_api/metrics_explorer_views/v1/common.ts index 8e8d1e755c8d..22aa3350ceee 100644 --- a/x-pack/plugins/infra/common/http_api/metrics_explorer_views/v1/common.ts +++ b/x-pack/plugins/infra/common/http_api/metrics_explorer_views/v1/common.ts @@ -9,7 +9,8 @@ import { either } from 'fp-ts/Either'; import { metricsExplorerViewRT } from '../../../metrics_explorer_views'; export const METRICS_EXPLORER_VIEW_URL = '/api/infra/metrics_explorer_views'; -export const METRICS_EXPLORER_VIEW_URL_ENTITY = `${METRICS_EXPLORER_VIEW_URL}/{metricsExplorerViewId}`; +export const METRICS_EXPLORER_VIEW_URL_ENTITY = + `${METRICS_EXPLORER_VIEW_URL}/{metricsExplorerViewId}` as const; export const getMetricsExplorerViewUrl = (metricsExplorerViewId?: string) => [METRICS_EXPLORER_VIEW_URL, metricsExplorerViewId].filter(Boolean).join('/'); diff --git a/x-pack/plugins/infra/common/plugin_config_types.ts b/x-pack/plugins/infra/common/plugin_config_types.ts index adff4cabe30a..89bbd1dbe4e5 100644 --- a/x-pack/plugins/infra/common/plugin_config_types.ts +++ b/x-pack/plugins/infra/common/plugin_config_types.ts @@ -25,10 +25,14 @@ export interface InfraConfig { }; }; }; + featureFlags: { + metricsExplorerEnabled: boolean; + }; } export const publicConfigKeys = { sources: true, + featureFlags: true, } as const; export type InfraPublicConfigKey = keyof { diff --git a/x-pack/plugins/infra/public/apps/metrics_app.tsx b/x-pack/plugins/infra/public/apps/metrics_app.tsx index 5366019d5ad8..2da9e1699514 100644 --- a/x-pack/plugins/infra/public/apps/metrics_app.tsx +++ b/x-pack/plugins/infra/public/apps/metrics_app.tsx @@ -13,6 +13,7 @@ import { Router, Routes, Route } from '@kbn/shared-ux-router'; import { AppMountParameters } from '@kbn/core/public'; import { Storage } from '@kbn/kibana-utils-plugin/public'; import '../index.scss'; +import { InfraPublicConfig } from '../../common/plugin_config_types'; import { LinkToMetricsPage } from '../pages/link_to/link_to_metrics'; import { InfrastructurePage } from '../pages/metrics'; import { InfraClientStartDeps, InfraClientStartExports } from '../types'; @@ -20,6 +21,7 @@ import { RedirectWithQueryParams } from '../utils/redirect_with_query_params'; import { CommonInfraProviders, CoreProviders } from './common_providers'; import { prepareMountElement } from './common_styles'; import { SourceProvider } from '../containers/metrics_source'; +import { PluginConfigProvider } from '../containers/plugin_config_context'; export const METRICS_APP_DATA_TEST_SUBJ = 'infraMetricsPage'; @@ -27,6 +29,7 @@ export const renderApp = ( core: CoreStart, plugins: InfraClientStartDeps, pluginStart: InfraClientStartExports, + pluginConfig: InfraPublicConfig, { element, history, setHeaderActionMenu, theme$ }: AppMountParameters ) => { const storage = new Storage(window.localStorage); @@ -39,6 +42,7 @@ export const renderApp = ( history={history} plugins={plugins} pluginStart={pluginStart} + pluginConfig={pluginConfig} setHeaderActionMenu={setHeaderActionMenu} storage={storage} theme$={theme$} @@ -56,11 +60,21 @@ const MetricsApp: React.FC<{ core: CoreStart; history: History; pluginStart: InfraClientStartExports; + pluginConfig: InfraPublicConfig; plugins: InfraClientStartDeps; setHeaderActionMenu: AppMountParameters['setHeaderActionMenu']; storage: Storage; theme$: AppMountParameters['theme$']; -}> = ({ core, history, pluginStart, plugins, setHeaderActionMenu, storage, theme$ }) => { +}> = ({ + core, + history, + pluginStart, + pluginConfig, + plugins, + setHeaderActionMenu, + storage, + theme$, +}) => { const uiCapabilities = core.application.capabilities; return ( @@ -74,23 +88,25 @@ const MetricsApp: React.FC<{ observabilityAIAssistant={plugins.observabilityAIAssistant} > - - - - {uiCapabilities?.infrastructure?.show && ( - - )} - {uiCapabilities?.infrastructure?.show && ( - - )} - {uiCapabilities?.infrastructure?.show && ( - - )} - {uiCapabilities?.infrastructure?.show && ( - - )} - - + + + + + {uiCapabilities?.infrastructure?.show && ( + + )} + {uiCapabilities?.infrastructure?.show && ( + + )} + {uiCapabilities?.infrastructure?.show && ( + + )} + {uiCapabilities?.infrastructure?.show && ( + + )} + + + diff --git a/x-pack/plugins/infra/public/containers/plugin_config_context.test.tsx b/x-pack/plugins/infra/public/containers/plugin_config_context.test.tsx new file mode 100644 index 000000000000..2b89e4b996da --- /dev/null +++ b/x-pack/plugins/infra/public/containers/plugin_config_context.test.tsx @@ -0,0 +1,32 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { renderHook } from '@testing-library/react-hooks'; +import React from 'react'; +import { PluginConfigProvider, usePluginConfig } from './plugin_config_context'; + +describe('usePluginConfig()', () => { + it('throws an error if the context value was not set before using the hook', () => { + const { result } = renderHook(() => usePluginConfig()); + + expect(result.error).not.toEqual(undefined); + }); + + it('returns the plugin config what was set through the provider', () => { + const config = { + featureFlags: { metricsExplorerEnabled: false }, + }; + const { result } = renderHook(() => usePluginConfig(), { + wrapper: ({ children }) => { + return {children}; + }, + }); + + expect(result.error).toEqual(undefined); + expect(result.current).toEqual(config); + }); +}); diff --git a/x-pack/plugins/infra/public/containers/plugin_config_context.ts b/x-pack/plugins/infra/public/containers/plugin_config_context.ts new file mode 100644 index 000000000000..a9b91c3f1aaa --- /dev/null +++ b/x-pack/plugins/infra/public/containers/plugin_config_context.ts @@ -0,0 +1,25 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { createContext, useContext } from 'react'; +import { InfraPublicConfig } from '../../common/plugin_config_types'; + +const PluginConfigContext = createContext(undefined); + +export const usePluginConfig = (): InfraPublicConfig => { + const context = useContext(PluginConfigContext); + + if (context === undefined) { + throw new Error( + 'PluginConfigContext value was not initialized. Use context provider to set the value before using it.' + ); + } + + return context; +}; + +export const PluginConfigProvider = PluginConfigContext.Provider; diff --git a/x-pack/plugins/infra/public/hooks/use_metrics_explorer_views.ts b/x-pack/plugins/infra/public/hooks/use_metrics_explorer_views.ts index dac743a1f219..7e0eb3bd387a 100644 --- a/x-pack/plugins/infra/public/hooks/use_metrics_explorer_views.ts +++ b/x-pack/plugins/infra/public/hooks/use_metrics_explorer_views.ts @@ -24,10 +24,10 @@ import { UpdateMetricsExplorerViewAttributesRequestPayload, } from '../../common/http_api/latest'; import { MetricsExplorerView } from '../../common/metrics_explorer_views'; -import { useKibanaContextForPlugin } from './use_kibana'; import { useUrlState } from '../utils/use_url_state'; import { useSavedViewsNotifier } from './use_saved_views_notifier'; import { useSourceContext } from '../containers/metrics_source'; +import { useKibanaContextForPlugin } from './use_kibana'; export type UseMetricsExplorerViewsResult = SavedViewResult< MetricsExplorerView, @@ -44,6 +44,11 @@ const queryKeys = { export const useMetricsExplorerViews = (): UseMetricsExplorerViewsResult => { const { metricsExplorerViews } = useKibanaContextForPlugin().services; + + if (metricsExplorerViews === undefined) { + throw new Error('MetricsExplorerViews service has not been initialized.'); + } + const trackMetric = useUiTracker({ app: 'infra_metrics' }); const queryClient = useQueryClient(); diff --git a/x-pack/plugins/infra/public/pages/metrics/index.tsx b/x-pack/plugins/infra/public/pages/metrics/index.tsx index 562c7a43175c..d0e41a68446a 100644 --- a/x-pack/plugins/infra/public/pages/metrics/index.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/index.tsx @@ -8,7 +8,6 @@ import { i18n } from '@kbn/i18n'; import React, { useContext } from 'react'; -import { RouteComponentProps } from 'react-router-dom'; import { Routes, Route } from '@kbn/shared-ux-router'; import { EuiErrorBoundary, EuiHeaderLinks, EuiHeaderLink } from '@elastic/eui'; @@ -37,12 +36,14 @@ import { HeaderActionMenuContext } from '../../utils/header_action_menu_provider import { CreateDerivedIndexPattern, useSourceContext } from '../../containers/metrics_source'; import { NotFoundPage } from '../404'; import { ReactQueryProvider } from '../../containers/react_query_provider'; +import { usePluginConfig } from '../../containers/plugin_config_context'; const ADD_DATA_LABEL = i18n.translate('xpack.infra.metricsHeaderAddDataButtonLabel', { defaultMessage: 'Add data', }); -export const InfrastructurePage = ({ match }: RouteComponentProps) => { +export const InfrastructurePage = () => { + const config = usePluginConfig(); const uiCapabilities = useKibana().services.application?.capabilities; const { setHeaderActionMenu, theme$ } = useContext(HeaderActionMenuContext); @@ -96,19 +97,21 @@ export const InfrastructurePage = ({ match }: RouteComponentProps) => { )} - - - - {source?.configuration ? ( - - ) : ( - - )} - - + {config.featureFlags.metricsExplorerEnabled && ( + + + + {source?.configuration ? ( + + ) : ( + + )} + + + )} @@ -131,10 +134,6 @@ const PageContent = (props: { const { createDerivedIndexPattern, configuration } = props; return ( - + ); }; diff --git a/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/index.tsx b/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/index.tsx index 4e1328fc3ae7..b1ea933788cd 100644 --- a/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/index.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/index.tsx @@ -23,6 +23,7 @@ import { MetricsPageTemplate } from '../page_template'; import { metricsExplorerTitle } from '../../../translations'; import { DerivedIndexPattern } from '../../../containers/metrics_source'; import { SavedViews } from './components/saved_views'; + interface MetricsExplorerPageProps { source: MetricsSourceConfigurationProperties; derivedIndexPattern: DerivedIndexPattern; diff --git a/x-pack/plugins/infra/public/plugin.ts b/x-pack/plugins/infra/public/plugin.ts index 0bcdfa7e04bc..b5c719be216f 100644 --- a/x-pack/plugins/infra/public/plugin.ts +++ b/x-pack/plugins/infra/public/plugin.ts @@ -50,7 +50,7 @@ import { getLogsHasDataFetcher, getLogsOverviewDataFetcher } from './utils/logs_ export class Plugin implements InfraClientPluginClass { public config: InfraPublicConfig; private inventoryViews: InventoryViewsService; - private metricsExplorerViews: MetricsExplorerViewsService; + private metricsExplorerViews?: MetricsExplorerViewsService; private telemetry: TelemetryService; private locators?: InfraLocators; private kibanaVersion: string; @@ -60,7 +60,9 @@ export class Plugin implements InfraClientPluginClass { this.config = context.config.get(); this.inventoryViews = new InventoryViewsService(); - this.metricsExplorerViews = new MetricsExplorerViewsService(); + this.metricsExplorerViews = this.config.featureFlags.metricsExplorerEnabled + ? new MetricsExplorerViewsService() + : undefined; this.telemetry = new TelemetryService(); this.kibanaVersion = context.env.packageInfo.version; } @@ -105,7 +107,9 @@ export class Plugin implements InfraClientPluginClass { /** !! Need to be kept in sync with the deepLinks in x-pack/plugins/infra/public/plugin.ts */ const infraEntries = [ { label: 'Inventory', app: 'metrics', path: '/inventory' }, - { label: 'Metrics Explorer', app: 'metrics', path: '/explorer' }, + ...(this.config.featureFlags.metricsExplorerEnabled + ? [{ label: 'Metrics Explorer', app: 'metrics', path: '/explorer' }] + : []), { label: 'Hosts', isBetaFeature: true, app: 'metrics', path: '/hosts' }, ]; pluginsSetup.observabilityShared.navigation.registerSections( @@ -231,13 +235,17 @@ export class Plugin implements InfraClientPluginClass { }), path: '/hosts', }, - { - id: 'metrics-explorer', - title: i18n.translate('xpack.infra.homePage.metricsExplorerTabTitle', { - defaultMessage: 'Metrics Explorer', - }), - path: '/explorer', - }, + ...(this.config.featureFlags.metricsExplorerEnabled + ? [ + { + id: 'metrics-explorer', + title: i18n.translate('xpack.infra.homePage.metricsExplorerTabTitle', { + defaultMessage: 'Metrics Explorer', + }), + path: '/explorer', + }, + ] + : []), { id: 'settings', title: i18n.translate('xpack.infra.homePage.settingsTabTitle', { @@ -266,6 +274,7 @@ export class Plugin implements InfraClientPluginClass { coreStart, { ...plugins, kibanaVersion: this.kibanaVersion }, pluginStart, + this.config, params ); }, @@ -313,7 +322,7 @@ export class Plugin implements InfraClientPluginClass { http: core.http, }); - const metricsExplorerViews = this.metricsExplorerViews.start({ + const metricsExplorerViews = this.metricsExplorerViews?.start({ http: core.http, }); diff --git a/x-pack/plugins/infra/public/types.ts b/x-pack/plugins/infra/public/types.ts index c663f57592f5..bbd2852ce00f 100644 --- a/x-pack/plugins/infra/public/types.ts +++ b/x-pack/plugins/infra/public/types.ts @@ -62,7 +62,7 @@ export interface InfraClientSetupExports { export interface InfraClientStartExports { inventoryViews: InventoryViewsServiceStart; - metricsExplorerViews: MetricsExplorerViewsServiceStart; + metricsExplorerViews?: MetricsExplorerViewsServiceStart; telemetry: ITelemetryClient; locators: InfraLocators; ContainerMetricsTable: ( diff --git a/x-pack/plugins/infra/server/lib/adapters/framework/kibana_framework_adapter.ts b/x-pack/plugins/infra/server/lib/adapters/framework/kibana_framework_adapter.ts index c10987b75c43..3b8b6ada3023 100644 --- a/x-pack/plugins/infra/server/lib/adapters/framework/kibana_framework_adapter.ts +++ b/x-pack/plugins/infra/server/lib/adapters/framework/kibana_framework_adapter.ts @@ -34,6 +34,7 @@ interface FrozenIndexParams { export class KibanaFramework { public router: IRouter; public plugins: InfraServerPluginSetupDeps; + public config: InfraConfig; private core: CoreSetup; constructor( @@ -44,6 +45,7 @@ export class KibanaFramework { this.router = core.http.createRouter(); this.plugins = plugins; this.core = core; + this.config = config; } public registerRoute( diff --git a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.test.ts b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.test.ts index 6eec0c9f2862..c28245ececfe 100644 --- a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.test.ts +++ b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.test.ts @@ -1898,6 +1898,9 @@ const createMockStaticConfiguration = (sources: any): InfraConfig => ({ inventory: { compositeSize: 2000, }, + featureFlags: { + metricsExplorerEnabled: true, + }, enabled: true, sources, }); diff --git a/x-pack/plugins/infra/server/lib/sources/sources.test.ts b/x-pack/plugins/infra/server/lib/sources/sources.test.ts index 183ce952583a..b149838c82b3 100644 --- a/x-pack/plugins/infra/server/lib/sources/sources.test.ts +++ b/x-pack/plugins/infra/server/lib/sources/sources.test.ts @@ -125,6 +125,9 @@ const createMockStaticConfiguration = (sources: any): InfraConfig => ({ inventory: { compositeSize: 2000, }, + featureFlags: { + metricsExplorerEnabled: true, + }, sources, enabled: true, }); diff --git a/x-pack/plugins/infra/server/plugin.ts b/x-pack/plugins/infra/server/plugin.ts index 10bf7e37fb7c..50e0779928ec 100644 --- a/x-pack/plugins/infra/server/plugin.ts +++ b/x-pack/plugins/infra/server/plugin.ts @@ -6,7 +6,7 @@ */ import { Server } from '@hapi/hapi'; -import { schema } from '@kbn/config-schema'; +import { schema, offeringBasedSchema } from '@kbn/config-schema'; import { CoreStart, Plugin, @@ -80,6 +80,12 @@ export const config: PluginConfigDescriptor = { ), }) ), + featureFlags: schema.object({ + metricsExplorerEnabled: offeringBasedSchema({ + traditional: schema.boolean({ defaultValue: true }), + serverless: schema.boolean({ defaultValue: false }), + }), + }), }), deprecations: configDeprecations, exposeToBrowser: publicConfigKeys, @@ -111,7 +117,7 @@ export class InfraServerPlugin private logsRules: RulesService; private metricsRules: RulesService; private inventoryViews: InventoryViewsService; - private metricsExplorerViews: MetricsExplorerViewsService; + private metricsExplorerViews?: MetricsExplorerViewsService; constructor(context: PluginInitializerContext) { this.config = context.config.get(); @@ -129,9 +135,9 @@ export class InfraServerPlugin ); this.inventoryViews = new InventoryViewsService(this.logger.get('inventoryViews')); - this.metricsExplorerViews = new MetricsExplorerViewsService( - this.logger.get('metricsExplorerViews') - ); + this.metricsExplorerViews = this.config.featureFlags.metricsExplorerEnabled + ? new MetricsExplorerViewsService(this.logger.get('metricsExplorerViews')) + : undefined; } setup(core: InfraPluginCoreSetup, plugins: InfraServerPluginSetupDeps) { @@ -155,12 +161,14 @@ export class InfraServerPlugin // Setup infra services const inventoryViews = this.inventoryViews.setup(); - const metricsExplorerViews = this.metricsExplorerViews.setup(); + const metricsExplorerViews = this.metricsExplorerViews?.setup(); // Register saved object types core.savedObjects.registerType(infraSourceConfigurationSavedObjectType); core.savedObjects.registerType(inventoryViewSavedObjectType); - core.savedObjects.registerType(metricsExplorerViewSavedObjectType); + if (this.config.featureFlags.metricsExplorerEnabled) { + core.savedObjects.registerType(metricsExplorerViewSavedObjectType); + } // TODO: separate these out individually and do away with "domains" as a temporary group // and make them available via the request context so we can do away with @@ -255,7 +263,7 @@ export class InfraServerPlugin savedObjects: core.savedObjects, }); - const metricsExplorerViews = this.metricsExplorerViews.start({ + const metricsExplorerViews = this.metricsExplorerViews?.start({ infraSources: this.libs.sources, savedObjects: core.savedObjects, }); diff --git a/x-pack/plugins/infra/server/routes/metrics_explorer_views/create_metrics_explorer_view.ts b/x-pack/plugins/infra/server/routes/metrics_explorer_views/create_metrics_explorer_view.ts index d02ed1208eb1..45ff1010a902 100644 --- a/x-pack/plugins/infra/server/routes/metrics_explorer_views/create_metrics_explorer_view.ts +++ b/x-pack/plugins/infra/server/routes/metrics_explorer_views/create_metrics_explorer_view.ts @@ -15,6 +15,13 @@ import { } from '../../../common/http_api/latest'; import type { InfraBackendLibs } from '../../lib/infra_types'; +const NON_STARTED_SERVICE_ERROR = { + statusCode: 500, + body: { + message: `Handler for "POST ${METRICS_EXPLORER_VIEW_URL}" was registered but MetricsViewService has not started.`, + }, +}; + export const initCreateMetricsExplorerViewRoute = ({ framework, getStartServices, @@ -31,6 +38,11 @@ export const initCreateMetricsExplorerViewRoute = ({ async (_requestContext, request, response) => { const { body, query } = request; const [, , { metricsExplorerViews }] = await getStartServices(); + + if (metricsExplorerViews === undefined) { + return response.customError(NON_STARTED_SERVICE_ERROR); + } + const metricsExplorerViewsClient = metricsExplorerViews.getScopedClient(request); try { diff --git a/x-pack/plugins/infra/server/routes/metrics_explorer_views/delete_metrics_explorer_view.ts b/x-pack/plugins/infra/server/routes/metrics_explorer_views/delete_metrics_explorer_view.ts index a3b6f8b05f09..05e5723ded70 100644 --- a/x-pack/plugins/infra/server/routes/metrics_explorer_views/delete_metrics_explorer_view.ts +++ b/x-pack/plugins/infra/server/routes/metrics_explorer_views/delete_metrics_explorer_view.ts @@ -13,6 +13,13 @@ import { } from '../../../common/http_api/latest'; import type { InfraBackendLibs } from '../../lib/infra_types'; +const NON_STARTED_SERVICE_ERROR = { + statusCode: 500, + body: { + message: `Handler for "DELETE ${METRICS_EXPLORER_VIEW_URL_ENTITY}" was registered but MetricsViewService has not started.`, + }, +}; + export const initDeleteMetricsExplorerViewRoute = ({ framework, getStartServices, @@ -28,6 +35,11 @@ export const initDeleteMetricsExplorerViewRoute = ({ async (_requestContext, request, response) => { const { params } = request; const [, , { metricsExplorerViews }] = await getStartServices(); + + if (metricsExplorerViews === undefined) { + return response.customError(NON_STARTED_SERVICE_ERROR); + } + const metricsExplorerViewsClient = metricsExplorerViews.getScopedClient(request); try { diff --git a/x-pack/plugins/infra/server/routes/metrics_explorer_views/find_metrics_explorer_view.ts b/x-pack/plugins/infra/server/routes/metrics_explorer_views/find_metrics_explorer_view.ts index fbae7790b04e..d915b545de1e 100644 --- a/x-pack/plugins/infra/server/routes/metrics_explorer_views/find_metrics_explorer_view.ts +++ b/x-pack/plugins/infra/server/routes/metrics_explorer_views/find_metrics_explorer_view.ts @@ -13,6 +13,13 @@ import { } from '../../../common/http_api/latest'; import type { InfraBackendLibs } from '../../lib/infra_types'; +const NON_STARTED_SERVICE_ERROR = { + statusCode: 500, + body: { + message: `Handler for "GET ${METRICS_EXPLORER_VIEW_URL}" was registered but MetricsViewService has not started.`, + }, +}; + export const initFindMetricsExplorerViewRoute = ({ framework, getStartServices, @@ -28,6 +35,11 @@ export const initFindMetricsExplorerViewRoute = ({ async (_requestContext, request, response) => { const { query } = request; const [, , { metricsExplorerViews }] = await getStartServices(); + + if (metricsExplorerViews === undefined) { + return response.customError(NON_STARTED_SERVICE_ERROR); + } + const metricsExplorerViewsClient = metricsExplorerViews.getScopedClient(request); try { diff --git a/x-pack/plugins/infra/server/routes/metrics_explorer_views/get_metrics_explorer_view.ts b/x-pack/plugins/infra/server/routes/metrics_explorer_views/get_metrics_explorer_view.ts index b8e71a3c662d..7582bf22d80e 100644 --- a/x-pack/plugins/infra/server/routes/metrics_explorer_views/get_metrics_explorer_view.ts +++ b/x-pack/plugins/infra/server/routes/metrics_explorer_views/get_metrics_explorer_view.ts @@ -15,6 +15,13 @@ import { } from '../../../common/http_api/latest'; import type { InfraBackendLibs } from '../../lib/infra_types'; +const NON_STARTED_SERVICE_ERROR = { + statusCode: 500, + body: { + message: `Handler for "GET ${METRICS_EXPLORER_VIEW_URL_ENTITY}" was registered but MetricsViewService has not started.`, + }, +}; + export const initGetMetricsExplorerViewRoute = ({ framework, getStartServices, @@ -31,6 +38,11 @@ export const initGetMetricsExplorerViewRoute = ({ async (_requestContext, request, response) => { const { params, query } = request; const [, , { metricsExplorerViews }] = await getStartServices(); + + if (metricsExplorerViews === undefined) { + return response.customError(NON_STARTED_SERVICE_ERROR); + } + const metricsExplorerViewsClient = metricsExplorerViews.getScopedClient(request); try { diff --git a/x-pack/plugins/infra/server/routes/metrics_explorer_views/index.ts b/x-pack/plugins/infra/server/routes/metrics_explorer_views/index.ts index e4a616537442..ae95dc9c43c2 100644 --- a/x-pack/plugins/infra/server/routes/metrics_explorer_views/index.ts +++ b/x-pack/plugins/infra/server/routes/metrics_explorer_views/index.ts @@ -15,6 +15,10 @@ import { initUpdateMetricsExplorerViewRoute } from './update_metrics_explorer_vi export const initMetricsExplorerViewRoutes = ( dependencies: Pick ) => { + if (!dependencies.framework.config.featureFlags.metricsExplorerEnabled) { + return; + } + initCreateMetricsExplorerViewRoute(dependencies); initDeleteMetricsExplorerViewRoute(dependencies); initFindMetricsExplorerViewRoute(dependencies); diff --git a/x-pack/plugins/infra/server/routes/metrics_explorer_views/update_metrics_explorer_view.ts b/x-pack/plugins/infra/server/routes/metrics_explorer_views/update_metrics_explorer_view.ts index ebd8caef8e03..fc7f8ecd7893 100644 --- a/x-pack/plugins/infra/server/routes/metrics_explorer_views/update_metrics_explorer_view.ts +++ b/x-pack/plugins/infra/server/routes/metrics_explorer_views/update_metrics_explorer_view.ts @@ -16,6 +16,13 @@ import { } from '../../../common/http_api/latest'; import type { InfraBackendLibs } from '../../lib/infra_types'; +const NON_STARTED_SERVICE_ERROR = { + statusCode: 500, + body: { + message: `Handler for "PUT ${METRICS_EXPLORER_VIEW_URL_ENTITY}" was registered but MetricsViewService has not started.`, + }, +}; + export const initUpdateMetricsExplorerViewRoute = ({ framework, getStartServices, @@ -33,6 +40,11 @@ export const initUpdateMetricsExplorerViewRoute = ({ async (_requestContext, request, response) => { const { body, params, query } = request; const [, , { metricsExplorerViews }] = await getStartServices(); + + if (metricsExplorerViews === undefined) { + return response.customError(NON_STARTED_SERVICE_ERROR); + } + const metricsExplorerViewsClient = metricsExplorerViews.getScopedClient(request); try { diff --git a/x-pack/plugins/infra/server/types.ts b/x-pack/plugins/infra/server/types.ts index e9d9faa548bb..8fc3576027d6 100644 --- a/x-pack/plugins/infra/server/types.ts +++ b/x-pack/plugins/infra/server/types.ts @@ -27,12 +27,12 @@ export interface InfraPluginSetup { sourceProperties: InfraStaticSourceConfiguration ) => void; inventoryViews: InventoryViewsServiceSetup; - metricsExplorerViews: MetricsExplorerViewsServiceSetup; + metricsExplorerViews?: MetricsExplorerViewsServiceSetup; } export interface InfraPluginStart { inventoryViews: InventoryViewsServiceStart; - metricsExplorerViews: MetricsExplorerViewsServiceStart; + metricsExplorerViews?: MetricsExplorerViewsServiceStart; } export type MlSystem = ReturnType;