From e238b93f45180b7fee80dc6d07b53c7b077cca5a Mon Sep 17 00:00:00 2001 From: criamico Date: Tue, 13 Jun 2023 16:47:05 +0200 Subject: [PATCH 1/5] Replace usage of public SO client with Fleet get Bulk Assets api --- x-pack/plugins/fleet/public/index.ts | 2 +- .../elasticsearch/ingest_pipeline_modal.tsx | 21 +++++++++++++------ 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/x-pack/plugins/fleet/public/index.ts b/x-pack/plugins/fleet/public/index.ts index a745c59319e8c..5e26f792f22d9 100644 --- a/x-pack/plugins/fleet/public/index.ts +++ b/x-pack/plugins/fleet/public/index.ts @@ -15,7 +15,7 @@ export const plugin = (initializerContext: PluginInitializerContext) => { return new FleetPlugin(initializerContext); }; -export type { NewPackagePolicy } from './types'; +export type { NewPackagePolicy, GetBulkAssetsResponse } from './types'; export type { AgentDetailsReassignPolicyAction, AgentPolicyDetailsDeployAgentAction, diff --git a/x-pack/plugins/monitoring/public/application/pages/elasticsearch/ingest_pipeline_modal.tsx b/x-pack/plugins/monitoring/public/application/pages/elasticsearch/ingest_pipeline_modal.tsx index 32bf9ce1af4f7..6edab58ae4816 100644 --- a/x-pack/plugins/monitoring/public/application/pages/elasticsearch/ingest_pipeline_modal.tsx +++ b/x-pack/plugins/monitoring/public/application/pages/elasticsearch/ingest_pipeline_modal.tsx @@ -12,7 +12,7 @@ import { FormattedMessage } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; import { EuiCallOut, EuiConfirmModal, EuiSpacer } from '@elastic/eui'; import { DashboardStart } from '@kbn/dashboard-plugin/public'; -import { FleetStart } from '@kbn/fleet-plugin/public'; +import { FleetStart, GetBulkAssetsResponse } from '@kbn/fleet-plugin/public'; const INGEST_PIPELINE_DASHBOARD_ID = 'elasticsearch-metrics-ingest-pipelines'; @@ -25,11 +25,20 @@ const INGEST_PIPELINE_DASHBOARD_ID = 'elasticsearch-metrics-ingest-pipelines'; export const ingestPipelineTabOnClick = async ( services: Partial ) => { - const dashboard = await services.savedObjects!.client.get( - 'dashboard', - INGEST_PIPELINE_DASHBOARD_ID - ); - const dashboardFound = !dashboard.error && dashboard.attributes; + const response = await services.http!.fetch('/api/fleet/epm/bulk_assets', { + method: 'POST', + body: JSON.stringify({ + assetIds: [ + { + id: INGEST_PIPELINE_DASHBOARD_ID, + type: 'dashboard', + }, + ], + }), + }); + const dashboardFound = + response?.items?.length && + response?.items.some((item) => item.id === INGEST_PIPELINE_DASHBOARD_ID); const navigateToDashboard = () => services.dashboard!.locator!.navigate({ From 01f5d02848fd95339d0c8d32330d8f41777297bc Mon Sep 17 00:00:00 2001 From: criamico Date: Thu, 15 Jun 2023 10:01:04 +0200 Subject: [PATCH 2/5] Export hook from Fleet to replace http request --- x-pack/plugins/fleet/public/index.ts | 2 +- x-pack/plugins/fleet/public/plugin.ts | 18 +++++++- x-pack/plugins/fleet/public/types/index.ts | 1 + .../fleet/server/routes/epm/handlers.ts | 30 ++---------- .../services/epm/packages/get_bulk_assets.ts | 46 +++++++++++++++++++ .../server/services/epm/packages/index.ts | 1 + .../elasticsearch/ingest_pipeline_modal.tsx | 23 ++++------ 7 files changed, 81 insertions(+), 40 deletions(-) create mode 100644 x-pack/plugins/fleet/server/services/epm/packages/get_bulk_assets.ts diff --git a/x-pack/plugins/fleet/public/index.ts b/x-pack/plugins/fleet/public/index.ts index 5e26f792f22d9..a46efe49d5df6 100644 --- a/x-pack/plugins/fleet/public/index.ts +++ b/x-pack/plugins/fleet/public/index.ts @@ -15,7 +15,7 @@ export const plugin = (initializerContext: PluginInitializerContext) => { return new FleetPlugin(initializerContext); }; -export type { NewPackagePolicy, GetBulkAssetsResponse } from './types'; +export type { NewPackagePolicy, KibanaSavedObjectType } from './types'; export type { AgentDetailsReassignPolicyAction, AgentPolicyDetailsDeployAgentAction, diff --git a/x-pack/plugins/fleet/public/plugin.ts b/x-pack/plugins/fleet/public/plugin.ts index 6d41e4073afa0..5cf01a5083a37 100644 --- a/x-pack/plugins/fleet/public/plugin.ts +++ b/x-pack/plugins/fleet/public/plugin.ts @@ -44,6 +44,8 @@ import type { LicensingPluginStart } from '@kbn/licensing-plugin/public'; import type { CloudSetup } from '@kbn/cloud-plugin/public'; import type { GlobalSearchPluginSetup } from '@kbn/global-search-plugin/public'; +import type { SendRequestResponse } from '@kbn/es-ui-shared-plugin/public'; + import type { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public'; import type { GuidedOnboardingPluginStart } from '@kbn/guided-onboarding-plugin/public'; @@ -63,13 +65,21 @@ import { createPackageSearchProvider } from './search_provider'; import { TutorialDirectoryHeaderLink, TutorialModuleNotice } from './components/home_integration'; import { createExtensionRegistrationCallback } from './services/ui_extensions'; import { ExperimentalFeaturesService } from './services/experimental_features'; -import type { UIExtensionRegistrationCallback, UIExtensionsStorage } from './types'; +import type { + UIExtensionRegistrationCallback, + UIExtensionsStorage, + GetBulkAssetsRequest, + GetBulkAssetsResponse, +} from './types'; import { LazyCustomLogsAssetsExtension } from './lazy_custom_logs_assets_extension'; export type { FleetConfigType } from '../common/types'; import { setCustomIntegrations, setCustomIntegrationsStart } from './services/custom_integrations'; +import type { RequestError } from './hooks'; +import { sendGetBulkAssets } from './hooks'; + // We need to provide an object instead of void so that dependent plugins know when Fleet // is disabled. // eslint-disable-next-line @typescript-eslint/no-empty-interface @@ -83,6 +93,9 @@ export interface FleetStart { authz: FleetAuthz; registerExtension: UIExtensionRegistrationCallback; isInitialized: () => Promise; + getBulkAssets: ( + body: GetBulkAssetsRequest['body'] + ) => Promise>; } export interface FleetSetupDeps { @@ -315,6 +328,9 @@ export class FleetPlugin implements Plugin > = async (context, request, response) => { try { - const savedObjectsClient = (await context.fleet).internalSoClient; const { assetIds } = request.body; + const savedObjectsClient = (await context.fleet).internalSoClient; + const assets = await getBulkAssets(savedObjectsClient, assetIds as AssetSOObject[]); - const { resolved_objects: resolvedObjects } = - await savedObjectsClient.bulkResolve(assetIds); - const res: SimpleSOAssetType[] = resolvedObjects - .map(({ saved_object: savedObject }) => savedObject) - .filter( - (savedObject) => - savedObject?.error?.statusCode !== 404 && allowedAssetTypesLookup.has(savedObject.type) - ) - .map((obj) => { - return { - id: obj.id, - type: obj.type as unknown as ElasticsearchAssetType | KibanaSavedObjectType, - updatedAt: obj.updated_at, - attributes: { - title: obj.attributes.title, - description: obj.attributes.description, - }, - }; - }); const body: GetBulkAssetsResponse = { - items: res, + items: assets, }; return response.ok({ body }); } catch (error) { diff --git a/x-pack/plugins/fleet/server/services/epm/packages/get_bulk_assets.ts b/x-pack/plugins/fleet/server/services/epm/packages/get_bulk_assets.ts new file mode 100644 index 0000000000000..ebeaed684c3a0 --- /dev/null +++ b/x-pack/plugins/fleet/server/services/epm/packages/get_bulk_assets.ts @@ -0,0 +1,46 @@ +/* + * 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 type { SavedObjectsClientContract } from '@kbn/core/server'; + +import type { + AssetSOObject, + ElasticsearchAssetType, + KibanaSavedObjectType, + SimpleSOAssetType, +} from '../../../../common'; + +import { allowedAssetTypesLookup } from '../../../../common/constants'; + +import type { SimpleSOAssetAttributes } from '../../../types'; + +export async function getBulkAssets( + soClient: SavedObjectsClientContract, + assetIds: AssetSOObject[] +) { + const { resolved_objects: resolvedObjects } = await soClient.bulkResolve( + assetIds + ); + const res: SimpleSOAssetType[] = resolvedObjects + .map(({ saved_object: savedObject }) => savedObject) + .filter( + (savedObject) => + savedObject?.error?.statusCode !== 404 && allowedAssetTypesLookup.has(savedObject.type) + ) + .map((obj) => { + return { + id: obj.id, + type: obj.type as unknown as ElasticsearchAssetType | KibanaSavedObjectType, + updatedAt: obj.updated_at, + attributes: { + title: obj.attributes.title, + description: obj.attributes.description, + }, + }; + }); + return res; +} diff --git a/x-pack/plugins/fleet/server/services/epm/packages/index.ts b/x-pack/plugins/fleet/server/services/epm/packages/index.ts index 1141100b10e1a..cbac974f497a2 100644 --- a/x-pack/plugins/fleet/server/services/epm/packages/index.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/index.ts @@ -27,6 +27,7 @@ export { } from './get'; export { getBundledPackages } from './bundled_packages'; +export { getBulkAssets } from './get_bulk_assets'; export type { BulkInstallResponse, IBulkInstallPackageError } from './install'; export { handleInstallPackageFailure, installPackage, ensureInstalledPackage } from './install'; diff --git a/x-pack/plugins/monitoring/public/application/pages/elasticsearch/ingest_pipeline_modal.tsx b/x-pack/plugins/monitoring/public/application/pages/elasticsearch/ingest_pipeline_modal.tsx index 6edab58ae4816..91a7ddd332fbf 100644 --- a/x-pack/plugins/monitoring/public/application/pages/elasticsearch/ingest_pipeline_modal.tsx +++ b/x-pack/plugins/monitoring/public/application/pages/elasticsearch/ingest_pipeline_modal.tsx @@ -12,7 +12,7 @@ import { FormattedMessage } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; import { EuiCallOut, EuiConfirmModal, EuiSpacer } from '@elastic/eui'; import { DashboardStart } from '@kbn/dashboard-plugin/public'; -import { FleetStart, GetBulkAssetsResponse } from '@kbn/fleet-plugin/public'; +import { FleetStart, KibanaSavedObjectType } from '@kbn/fleet-plugin/public'; const INGEST_PIPELINE_DASHBOARD_ID = 'elasticsearch-metrics-ingest-pipelines'; @@ -25,20 +25,17 @@ const INGEST_PIPELINE_DASHBOARD_ID = 'elasticsearch-metrics-ingest-pipelines'; export const ingestPipelineTabOnClick = async ( services: Partial ) => { - const response = await services.http!.fetch('/api/fleet/epm/bulk_assets', { - method: 'POST', - body: JSON.stringify({ - assetIds: [ - { - id: INGEST_PIPELINE_DASHBOARD_ID, - type: 'dashboard', - }, - ], - }), + const response = await services.fleet?.getBulkAssets({ + assetIds: [ + { + id: INGEST_PIPELINE_DASHBOARD_ID, + type: 'dashboard' as KibanaSavedObjectType, + }, + ], }); const dashboardFound = - response?.items?.length && - response?.items.some((item) => item.id === INGEST_PIPELINE_DASHBOARD_ID); + response?.data?.items?.length && + response.data.items.some((item) => item.id === INGEST_PIPELINE_DASHBOARD_ID); const navigateToDashboard = () => services.dashboard!.locator!.navigate({ From 356b72afd29959c0931fd4ba5447c8fac2aec930 Mon Sep 17 00:00:00 2001 From: criamico Date: Thu, 15 Jun 2023 11:21:19 +0200 Subject: [PATCH 3/5] Fix tests --- x-pack/plugins/fleet/public/mock/plugin_interfaces.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/x-pack/plugins/fleet/public/mock/plugin_interfaces.ts b/x-pack/plugins/fleet/public/mock/plugin_interfaces.ts index 7a23e066e286e..9385464bc4abb 100644 --- a/x-pack/plugins/fleet/public/mock/plugin_interfaces.ts +++ b/x-pack/plugins/fleet/public/mock/plugin_interfaces.ts @@ -34,5 +34,6 @@ export const createStartMock = (extensionsStorage: UIExtensionsStorage = {}): Mo writeIntegrationPolicies: true, }, }, + getBulkAssets: jest.fn(), }; }; From 469bfc5639e048f44d34ab71ad4a1355e814b667 Mon Sep 17 00:00:00 2001 From: criamico Date: Thu, 15 Jun 2023 17:13:53 +0200 Subject: [PATCH 4/5] Wrap exported function into hooks parameter --- x-pack/plugins/fleet/public/plugin.ts | 14 +++++++++----- .../pages/elasticsearch/ingest_pipeline_modal.tsx | 2 +- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/fleet/public/plugin.ts b/x-pack/plugins/fleet/public/plugin.ts index 5cf01a5083a37..3705e523b2f23 100644 --- a/x-pack/plugins/fleet/public/plugin.ts +++ b/x-pack/plugins/fleet/public/plugin.ts @@ -93,9 +93,11 @@ export interface FleetStart { authz: FleetAuthz; registerExtension: UIExtensionRegistrationCallback; isInitialized: () => Promise; - getBulkAssets: ( - body: GetBulkAssetsRequest['body'] - ) => Promise>; + hooks: { + getBulkAssets: ( + body: GetBulkAssetsRequest['body'] + ) => Promise>; + }; } export interface FleetSetupDeps { @@ -329,8 +331,10 @@ export class FleetPlugin implements Plugin ) => { - const response = await services.fleet?.getBulkAssets({ + const response = await services.fleet?.hooks.getBulkAssets({ assetIds: [ { id: INGEST_PIPELINE_DASHBOARD_ID, From 5eb5b07c836a7a9f7c76e6e79469ad88aaf15381 Mon Sep 17 00:00:00 2001 From: criamico Date: Thu, 15 Jun 2023 18:00:04 +0200 Subject: [PATCH 5/5] add epm parameter to exported hooks --- .../plugins/fleet/public/mock/plugin_interfaces.ts | 2 +- x-pack/plugins/fleet/public/plugin.ts | 14 +++++++++----- .../pages/elasticsearch/ingest_pipeline_modal.tsx | 2 +- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/x-pack/plugins/fleet/public/mock/plugin_interfaces.ts b/x-pack/plugins/fleet/public/mock/plugin_interfaces.ts index 9385464bc4abb..c85e9e713ebcf 100644 --- a/x-pack/plugins/fleet/public/mock/plugin_interfaces.ts +++ b/x-pack/plugins/fleet/public/mock/plugin_interfaces.ts @@ -34,6 +34,6 @@ export const createStartMock = (extensionsStorage: UIExtensionsStorage = {}): Mo writeIntegrationPolicies: true, }, }, - getBulkAssets: jest.fn(), + hooks: { epm: { getBulkAssets: jest.fn() } }, }; }; diff --git a/x-pack/plugins/fleet/public/plugin.ts b/x-pack/plugins/fleet/public/plugin.ts index 3705e523b2f23..a433ba3fde50d 100644 --- a/x-pack/plugins/fleet/public/plugin.ts +++ b/x-pack/plugins/fleet/public/plugin.ts @@ -94,9 +94,11 @@ export interface FleetStart { registerExtension: UIExtensionRegistrationCallback; isInitialized: () => Promise; hooks: { - getBulkAssets: ( - body: GetBulkAssetsRequest['body'] - ) => Promise>; + epm: { + getBulkAssets: ( + body: GetBulkAssetsRequest['body'] + ) => Promise>; + }; }; } @@ -332,8 +334,10 @@ export class FleetPlugin implements Plugin ) => { - const response = await services.fleet?.hooks.getBulkAssets({ + const response = await services.fleet?.hooks.epm.getBulkAssets({ assetIds: [ { id: INGEST_PIPELINE_DASHBOARD_ID,