diff --git a/x-pack/plugins/ingest_manager/common/types/models/epm.ts b/x-pack/plugins/ingest_manager/common/types/models/epm.ts index 53ad0310ea6134..fea9da95529efd 100644 --- a/x-pack/plugins/ingest_manager/common/types/models/epm.ts +++ b/x-pack/plugins/ingest_manager/common/types/models/epm.ts @@ -57,6 +57,7 @@ export interface RegistryPackage { icons?: RegistryImage[]; assets?: string[]; internal?: boolean; + removable?: boolean; format_version: string; datasets?: Dataset[]; datasources?: RegistryDatasource[]; diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/content.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/content.tsx index 0d4b3958953225..a3d24e7806f343 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/content.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/content.tsx @@ -50,10 +50,18 @@ export function Content(props: ContentProps) { type ContentPanelProps = PackageInfo & Pick; export function ContentPanel(props: ContentPanelProps) { - const { panel, name, version, assets, title } = props; + const { panel, name, version, assets, title, removable } = props; switch (panel) { case 'settings': - return ; + return ( + + ); case 'data-sources': return ; case 'overview': diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/settings_panel.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/settings_panel.tsx index ff7ecf97714b6b..f947466caf4b09 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/settings_panel.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/settings_panel.tsx @@ -13,8 +13,14 @@ import { InstallStatus, PackageInfo } from '../../../../types'; import { InstallationButton } from './installation_button'; import { useGetDatasources } from '../../../../hooks'; +const NoteLabel = () => ( + +); export const SettingsPanel = ( - props: Pick + props: Pick ) => { const getPackageInstallStatus = useGetPackageInstallStatus(); const { data: datasourcesData } = useGetDatasources({ @@ -22,10 +28,9 @@ export const SettingsPanel = ( page: 1, kuery: `datasources.package.name:${props.name}`, }); - const { name, title } = props; + const { name, title, removable } = props; const packageInstallStatus = getPackageInstallStatus(name); const packageHasDatasources = !!datasourcesData?.total; - return ( @@ -89,12 +94,12 @@ export const SettingsPanel = (

- {packageHasDatasources && ( + {packageHasDatasources && removable === true && (

- + + + ), + }} + /> +

+ )} + {removable === false && ( +

+ + ), }} diff --git a/x-pack/plugins/ingest_manager/server/saved_objects.ts b/x-pack/plugins/ingest_manager/server/saved_objects.ts index dc0b4695603e41..0a7229b1f28072 100644 --- a/x-pack/plugins/ingest_manager/server/saved_objects.ts +++ b/x-pack/plugins/ingest_manager/server/saved_objects.ts @@ -150,6 +150,7 @@ export const savedObjectMappings = { name: { type: 'keyword' }, version: { type: 'keyword' }, internal: { type: 'boolean' }, + removable: { type: 'boolean' }, es_index_patterns: { dynamic: false, type: 'object', diff --git a/x-pack/plugins/ingest_manager/server/services/epm/packages/install.ts b/x-pack/plugins/ingest_manager/server/services/epm/packages/install.ts index 0a7642752b3e98..be3982746ff663 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/packages/install.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/packages/install.ts @@ -90,7 +90,7 @@ export async function installPackage(options: { // TODO: change epm API to /packageName/version so we don't need to do this const [pkgName, pkgVersion] = pkgkey.split('-'); const registryPackageInfo = await Registry.fetchInfo(pkgName, pkgVersion); - const { internal = false } = registryPackageInfo; + const { internal = false, removable = true } = registryPackageInfo; const installKibanaAssetsPromise = installKibanaAssets({ savedObjectsClient, @@ -127,6 +127,7 @@ export async function installPackage(options: { pkgName, pkgVersion, internal, + removable, toSaveAssetRefs, toSaveESIndexPatterns, }); @@ -158,6 +159,7 @@ export async function saveInstallationReferences(options: { pkgName: string; pkgVersion: string; internal: boolean; + removable: boolean; toSaveAssetRefs: AssetReference[]; toSaveESIndexPatterns: Record; }) { @@ -166,6 +168,7 @@ export async function saveInstallationReferences(options: { pkgName, pkgVersion, internal, + removable, toSaveAssetRefs, toSaveESIndexPatterns, } = options; @@ -191,6 +194,7 @@ export async function saveInstallationReferences(options: { name: pkgName, version: pkgVersion, internal, + removable, }, { id: pkgName, overwrite: true } ); diff --git a/x-pack/plugins/ingest_manager/server/services/epm/packages/remove.ts b/x-pack/plugins/ingest_manager/server/services/epm/packages/remove.ts index a30acb97b99cf0..e5fac9b38a3c19 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/packages/remove.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/packages/remove.ts @@ -20,7 +20,10 @@ export async function removeInstallation(options: { // TODO: the epm api should change to /name/version so we don't need to do this const [pkgName] = pkgkey.split('-'); const installation = await getInstallation({ savedObjectsClient, pkgName }); - const installedObjects = installation?.installed || []; + if (!installation) throw new Error('integration does not exist'); + if (installation.removable === false) + throw new Error(`The ${pkgName} integration is installed by default and cannot be removed`); + const installedObjects = installation.installed || []; // Delete the manager saved object with references to the asset objects // could also update with [] or some other state