diff --git a/packages/kbn-optimizer/limits.yml b/packages/kbn-optimizer/limits.yml index 29a396e371b9d..484f21d3eaac7 100644 --- a/packages/kbn-optimizer/limits.yml +++ b/packages/kbn-optimizer/limits.yml @@ -27,7 +27,7 @@ pageLoadAssetSize: indexLifecycleManagement: 107090 indexManagement: 140608 infra: 184320 - fleet: 100000 + fleet: 126917 ingestPipelines: 58003 inputControlVis: 172675 inspector: 148711 diff --git a/x-pack/plugins/fleet/common/constants/epm.ts b/x-pack/plugins/fleet/common/constants/epm.ts index 07f6fa048dc42..776691a895c17 100644 --- a/x-pack/plugins/fleet/common/constants/epm.ts +++ b/x-pack/plugins/fleet/common/constants/epm.ts @@ -18,6 +18,9 @@ export const FLEET_SYNTHETICS_PACKAGE = 'synthetics'; export const FLEET_KUBERNETES_PACKAGE = 'kubernetes'; export const FLEET_CLOUD_SECURITY_POSTURE_PACKAGE = 'cloud_security_posture'; +export const PACKAGE_TEMPLATE_SUFFIX = '@package'; +export const USER_SETTINGS_TEMPLATE_SUFFIX = '@custom'; + export const FLEET_ELASTIC_AGENT_DETAILS_DASHBOARD_ID = 'elastic_agent-f47f18cc-9c7d-4278-b2ea-a6dee816d395'; /* diff --git a/x-pack/plugins/fleet/common/services/datastream_es_name.test.ts b/x-pack/plugins/fleet/common/services/datastream_es_name.test.ts new file mode 100644 index 0000000000000..8e1eb3b1b9f12 --- /dev/null +++ b/x-pack/plugins/fleet/common/services/datastream_es_name.test.ts @@ -0,0 +1,53 @@ +/* + * 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 { + getCustomPipelineNameForDatastream, + getRegistryDataStreamAssetBaseName, +} from './datastream_es_name'; + +describe('getCustomPipelineNameForDatastream', () => { + it('return the correct custom pipeline for datastream', () => { + const res = getCustomPipelineNameForDatastream({ + type: 'logs', + dataset: 'test', + } as any); + + expect(res).toBe('logs-test@custom'); + }); +}); + +describe('getRegistryDataStreamAssetBaseName', () => { + it('return the asset name', () => { + const dataStream = { + dataset: 'nginx.access', + title: 'Nginx Acess Logs', + release: 'beta', + type: 'logs', + ingest_pipeline: 'default', + package: 'nginx', + path: 'access', + }; + const name = getRegistryDataStreamAssetBaseName(dataStream); + expect(name).toStrictEqual('logs-nginx.access'); + }); + + it('return the asset name for hidden index', () => { + const dataStream = { + dataset: 'nginx.access', + title: 'Nginx Acess Logs', + release: 'beta', + type: 'logs', + ingest_pipeline: 'default', + package: 'nginx', + path: 'access', + hidden: true, + }; + const name = getRegistryDataStreamAssetBaseName(dataStream); + expect(name).toStrictEqual('.logs-nginx.access'); + }); +}); diff --git a/x-pack/plugins/fleet/common/services/datastream_es_name.ts b/x-pack/plugins/fleet/common/services/datastream_es_name.ts new file mode 100644 index 0000000000000..077f1f5f0dc7f --- /dev/null +++ b/x-pack/plugins/fleet/common/services/datastream_es_name.ts @@ -0,0 +1,58 @@ +/* + * 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 { USER_SETTINGS_TEMPLATE_SUFFIX, PACKAGE_TEMPLATE_SUFFIX } from '../constants'; + +/** + * Creates the base name for Elasticsearch assets in the form of + * {type}-{dataset} + */ +export function getRegistryDataStreamAssetBaseName(dataStream: { + dataset: string; + type: string; + hidden?: boolean; +}): string { + const baseName = `${dataStream.type}-${dataStream.dataset}`; + return dataStream.hidden ? `.${baseName}` : baseName; +} + +/** + * Return the name for a component template + */ +export function getComponentTemplateNameForDatastream( + dataStream: { + dataset: string; + type: string; + hidden?: boolean; + }, + suffix?: typeof PACKAGE_TEMPLATE_SUFFIX | typeof USER_SETTINGS_TEMPLATE_SUFFIX +): string { + return `${getRegistryDataStreamAssetBaseName(dataStream)}${suffix ?? ''}`; +} + +/** + * Return the ingest pipeline name for a datastream + */ +export const getPipelineNameForDatastream = ({ + dataStream, + packageVersion, +}: { + dataStream: { dataset: string; type: string }; + packageVersion: string; +}): string => { + return `${dataStream.type}-${dataStream.dataset}-${packageVersion}`; +}; + +/** + * Return the custom user ingest pipeline name for a datastream + */ +export const getCustomPipelineNameForDatastream = (dataStream: { + dataset: string; + type: string; +}): string => { + return `${dataStream.type}-${dataStream.dataset}@custom`; +}; diff --git a/x-pack/plugins/fleet/common/services/index.ts b/x-pack/plugins/fleet/common/services/index.ts index d8a7ed080ac63..3774abb1cc4b3 100644 --- a/x-pack/plugins/fleet/common/services/index.ts +++ b/x-pack/plugins/fleet/common/services/index.ts @@ -36,3 +36,9 @@ export { normalizeHostsForAgents } from './hosts_utils'; export { splitPkgKey } from './split_pkg_key'; export { getMaxPackageName } from './max_package_name'; export { getMinVersion, getMaxVersion } from './get_min_max_version'; +export { + getPipelineNameForDatastream, + getCustomPipelineNameForDatastream, + getRegistryDataStreamAssetBaseName, + getComponentTemplateNameForDatastream, +} from './datastream_es_name'; diff --git a/x-pack/plugins/fleet/kibana.json b/x-pack/plugins/fleet/kibana.json index 4bfc6e95f0157..409e9f2a896ae 100644 --- a/x-pack/plugins/fleet/kibana.json +++ b/x-pack/plugins/fleet/kibana.json @@ -9,7 +9,7 @@ "ui": true, "configPath": ["xpack", "fleet"], "requiredPlugins": ["licensing", "data", "encryptedSavedObjects", "navigation", "customIntegrations", "share", "spaces", "security", "unifiedSearch"], - "optionalPlugins": ["features", "cloud", "usageCollection", "home", "globalSearch", "telemetry", "discover"], + "optionalPlugins": ["features", "cloud", "usageCollection", "home", "globalSearch", "telemetry", "discover", "ingestPipelines"], "extraPublicDirs": ["common"], "requiredBundles": ["kibanaReact", "cloud", "esUiShared", "infra", "kibanaUtils", "usageCollection", "unifiedSearch"] } diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/datastream_hooks.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/datastream_hooks.tsx new file mode 100644 index 0000000000000..b8fd2fdcdc81d --- /dev/null +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/datastream_hooks.tsx @@ -0,0 +1,26 @@ +/* + * 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 { useRouteMatch } from 'react-router-dom'; + +import { useLink } from '../../../../hooks'; + +export function usePackagePolicyEditorPageUrl() { + const { + params: { packagePolicyId, policyId }, + } = useRouteMatch<{ policyId: string; packagePolicyId: string }>(); + const { getHref } = useLink(); + + return packagePolicyId && policyId + ? getHref('edit_integration', { + policyId, + packagePolicyId, + }) + : getHref('integration_policy_edit', { + packagePolicyId, + }); +} diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/datastream_mappings.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/datastream_mappings.tsx new file mode 100644 index 0000000000000..8a2f056233041 --- /dev/null +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/datastream_mappings.tsx @@ -0,0 +1,133 @@ +/* + * 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 React from 'react'; +import { EuiBasicTable, EuiFlexGroup, EuiFlexItem, EuiText, EuiTitle, EuiLink } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { i18n } from '@kbn/i18n'; + +import type { PackageInfo } from '../../../../types'; +import { getComponentTemplateNameForDatastream } from '../../../../../../../common'; +import { useStartServices } from '../../../../hooks'; + +import { usePackagePolicyEditorPageUrl } from './datastream_hooks'; + +export interface PackagePolicyEditorDatastreamMappingsProps { + packageInfo: PackageInfo; + dataStream: { dataset: string; type: string }; +} + +function useComponentTemplates(dataStream: { dataset: string; type: string }) { + return [ + { + templateName: getComponentTemplateNameForDatastream(dataStream, '@package'), + }, + { + templateName: getComponentTemplateNameForDatastream(dataStream, '@custom'), + canEdit: true, + }, + ]; +} + +export const PackagePolicyEditorDatastreamMappings: React.FunctionComponent< + PackagePolicyEditorDatastreamMappingsProps +> = ({ dataStream, packageInfo }) => { + const pageUrl = usePackagePolicyEditorPageUrl(); + + const { application, docLinks } = useStartServices(); + const componentTemplateItems = useComponentTemplates(dataStream); + + return ( + + + +
+ +
+
+
+ + + + + + ), + }} + /> + + + + { + const url = application.getUrlForApp('management', { + path: `/data/index_management/edit_component_template/${el.templateName}`, + }); + + application.navigateToUrl(`${url}?redirect_path=${pageUrl}`); + }, + available: ({ canEdit }) => !!canEdit, + }, + { + icon: 'inspect', + type: 'icon', + description: i18n.translate( + 'xpack.fleet.packagePolicyEditor.datastreamMappings.inspectBtn', + { + defaultMessage: 'Inspect mappings', + } + ), + name: 'inspect', + 'data-test-subj': 'datastreamInspectMappingsBtn', + isPrimary: true, + onClick: async (el) => { + const url = application.getUrlForApp('management', { + path: `/data/index_management/component_templates/${el.templateName}`, + }); + + application.navigateToUrl(`${url}?redirect_path=${pageUrl}`); + }, + }, + ], + }, + ]} + /> + +
+ ); +}; diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/datastream_pipelines.test.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/datastream_pipelines.test.tsx new file mode 100644 index 0000000000000..a68facb62c3b4 --- /dev/null +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/datastream_pipelines.test.tsx @@ -0,0 +1,78 @@ +/* + * 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 React from 'react'; + +import { createFleetTestRendererMock } from '../../../../../../mock'; +import { useGetPipeline } from '../../../../hooks'; + +import { PackagePolicyEditorDatastreamPipelines } from './datastream_pipelines'; + +const mockedUseGetPipeline = useGetPipeline as jest.MockedFunction; + +jest.mock('../../../../hooks', () => { + return { + ...jest.requireActual('../../../../hooks'), + FleetStatusProvider: (props: any) => { + return props.children; + }, + useFleetStatus: jest.fn().mockReturnValue({ isReady: true } as any), + useGetPipeline: jest.fn(), + }; +}); + +describe('DatastreamPipelines', () => { + it('should render with a add button if there is no custom pipeline', () => { + const renderer = createFleetTestRendererMock(); + mockedUseGetPipeline.mockReturnValue({ + isLoading: false, + error: { + statusCode: 404, + }, + } as any); + + const result = renderer.render( + + ); + + expect(result.queryByTestId('datastreamAddCustomIngestPipelineBtn')).not.toBeNull(); + expect(result.queryAllByTestId('datastreamInspectPipelineBtn')).toHaveLength(1); + expect(result.queryAllByTestId('datastreamEditPipelineBtn')).toHaveLength(0); + }); + + it('should render without a add button if there is a pipeline', () => { + const renderer = createFleetTestRendererMock(); + mockedUseGetPipeline.mockReturnValue({ + isLoading: false, + data: { + name: 'test', + }, + } as any); + + const result = renderer.render( + + ); + + expect(result.queryByTestId('datastreamAddCustomIngestPipelineBtn')).toBeNull(); + expect(result.queryAllByTestId('datastreamInspectPipelineBtn')).toHaveLength(2); + expect(result.queryAllByTestId('datastreamEditPipelineBtn')).toHaveLength(1); + }); +}); diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/datastream_pipelines.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/datastream_pipelines.tsx new file mode 100644 index 0000000000000..33c1be4703121 --- /dev/null +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/datastream_pipelines.tsx @@ -0,0 +1,227 @@ +/* + * 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 React, { useEffect, useMemo, useState } from 'react'; +import { i18n } from '@kbn/i18n'; +import { + EuiBasicTable, + EuiButtonEmpty, + EuiFlexGroup, + EuiFlexItem, + EuiText, + EuiTitle, + EuiSpacer, + EuiLink, +} from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n-react'; + +import type { PackageInfo } from '../../../../types'; +import { useStartServices, useGetPipeline } from '../../../../hooks'; +import { + getPipelineNameForDatastream, + getCustomPipelineNameForDatastream, +} from '../../../../../../../common'; + +import { usePackagePolicyEditorPageUrl } from './datastream_hooks'; + +export interface PackagePolicyEditorDatastreamPipelinesProps { + packageInfo: PackageInfo; + dataStream: { dataset: string; type: string }; +} + +interface PipelineItem { + pipelineName: string; + canEdit: boolean; +} + +function toPipelineItem(pipelineName: string, canEdit = false): PipelineItem { + return { pipelineName, canEdit }; +} + +function useDatastreamIngestPipelines( + packageInfo: PackageInfo, + dataStream: { dataset: string; type: string }, + pageUrl: string | null +) { + const [addPipelineUrl, setAddPipelineUrl] = useState(''); + + const { share } = useStartServices(); + const ingestPipelineLocator = share.url.locators.get('INGEST_PIPELINES_APP_LOCATOR'); + + const defaultPipelineName = getPipelineNameForDatastream({ + dataStream, + packageVersion: packageInfo.version, + }); + + const customPipelineName = getCustomPipelineNameForDatastream(dataStream); + + const res = useGetPipeline(customPipelineName); + + const pipelines: PipelineItem[] = useMemo(() => { + if (res.data) { + return [toPipelineItem(defaultPipelineName), toPipelineItem(customPipelineName, true)]; + } + return [toPipelineItem(defaultPipelineName)]; + }, [defaultPipelineName, customPipelineName, res.data]); + + useEffect(() => { + async function getUrl() { + if (!ingestPipelineLocator) { + return; + } + const createUrl = await ingestPipelineLocator.getUrl({ + page: 'pipeline_create', + }); + setAddPipelineUrl(`${createUrl}?name=${customPipelineName}&redirect_path=${pageUrl}`); + } + + getUrl(); + }, [customPipelineName, pageUrl, ingestPipelineLocator]); + + return { + isLoading: res.isLoading, + hasCustom: !res.isLoading && res.error?.statusCode !== 404, + pipelines, + addPipelineUrl, + }; +} + +export const PackagePolicyEditorDatastreamPipelines: React.FunctionComponent< + PackagePolicyEditorDatastreamPipelinesProps +> = ({ dataStream, packageInfo }) => { + const { application, share, docLinks } = useStartServices(); + const ingestPipelineLocator = share.url.locators.get('INGEST_PIPELINES_APP_LOCATOR'); + + const pageUrl = usePackagePolicyEditorPageUrl(); + + const { pipelines, addPipelineUrl, hasCustom, isLoading } = useDatastreamIngestPipelines( + packageInfo, + dataStream, + pageUrl + ); + + if (!dataStream) { + return null; + } + + return ( + + + +
+ +
+
+
+ + + + + + ), + }} + /> + + + + { + if (!ingestPipelineLocator) { + return; + } + const url = await ingestPipelineLocator.getUrl({ + page: 'pipeline_edit', + pipelineId: el.pipelineName, + }); + + application.navigateToUrl(`${url}?redirect_path=${pageUrl}`); + }, + available: ({ canEdit }) => canEdit, + }, + { + icon: 'inspect', + type: 'icon', + description: i18n.translate( + 'xpack.fleet.packagePolicyEditor.datastreamIngestPipelines.inspectBtn', + { + defaultMessage: 'Inspect pipeline', + } + ), + name: 'inspect', + 'data-test-subj': 'datastreamInspectPipelineBtn', + isPrimary: true, + onClick: async (el) => { + if (!ingestPipelineLocator) { + return; + } + const url = await ingestPipelineLocator.getUrl({ + page: 'pipeline_list', + }); + + application.navigateToUrl( + `${url}?pipeline=${el.pipelineName}&redirect_path=${pageUrl}` + ); + }, + }, + ], + }, + ]} + /> + + {!isLoading && !hasCustom && ( + + + + + + + )} +
+ ); +}; diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/index.ts b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/index.ts index 08099f4078a08..b81947f49e65b 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/index.ts +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/index.ts @@ -7,3 +7,7 @@ export { IntegrationBreadcrumb } from './integration_breadcrumb'; export * from './steps'; +export { PackagePolicyEditorDatastreamPipelines } from './datastream_pipelines'; +export type { PackagePolicyEditorDatastreamPipelinesProps } from './datastream_pipelines'; +export { PackagePolicyEditorDatastreamMappings } from './datastream_mappings'; +export type { PackagePolicyEditorDatastreamMappingsProps } from './datastream_mappings'; diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/components/package_policy_input_panel.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/components/package_policy_input_panel.tsx index 47056b1c2dabf..cc641812235ce 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/components/package_policy_input_panel.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/components/package_policy_input_panel.tsx @@ -20,7 +20,9 @@ import { } from '@elastic/eui'; import type { + NewPackagePolicy, NewPackagePolicyInput, + PackageInfo, PackagePolicyInputStream, RegistryInput, RegistryStream, @@ -40,7 +42,7 @@ const ShortenedHorizontalRule = styled(EuiHorizontalRule)` const shouldShowStreamsByDefault = ( packageInput: RegistryInput, - packageInputStreams: Array, + packageInputStreams: Array, packagePolicyInput: NewPackagePolicyInput ): boolean => { return ( @@ -63,7 +65,9 @@ const shouldShowStreamsByDefault = ( export const PackagePolicyInputPanel: React.FunctionComponent<{ packageInput: RegistryInput; - packageInputStreams: Array; + packageInfo: PackageInfo; + packagePolicy: NewPackagePolicy; + packageInputStreams: Array; packagePolicyInput: NewPackagePolicyInput; updatePackagePolicyInput: (updatedInput: Partial) => void; inputValidationResults: PackagePolicyInputValidationResults; @@ -71,8 +75,10 @@ export const PackagePolicyInputPanel: React.FunctionComponent<{ }> = memo( ({ packageInput, + packageInfo, packageInputStreams, packagePolicyInput, + packagePolicy, updatePackagePolicyInput, inputValidationResults, forceShowErrors, @@ -214,6 +220,8 @@ export const PackagePolicyInputPanel: React.FunctionComponent<{ {inputStreams.map(({ packageInputStream, packagePolicyInputStream }, index) => ( ) => void; inputStreamValidationResults: PackagePolicyConfigValidationResults; forceShowErrors?: boolean; }> = memo( ({ + packagePolicy, packageInputStream, + packageInfo, packagePolicyInputStream, updatePackagePolicyInputStream, inputStreamValidationResults, forceShowErrors, }) => { + const { + params: { packagePolicyId }, + } = useRouteMatch<{ packagePolicyId?: string }>(); + + const isPackagePolicyEdit = !!packagePolicyId; + // Showing advanced options toggle state const [isShowingAdvanced, setIsShowingAdvanced] = useState(); // Errors state const hasErrors = forceShowErrors && validationHasErrors(inputStreamValidationResults); - const requiredVars: RegistryVarsEntry[] = []; - // eslint-disable-next-line react-hooks/exhaustive-deps - const advancedVars: RegistryVarsEntry[] = []; + const [requiredVars, advancedVars] = useMemo(() => { + const _requiredVars: RegistryVarsEntry[] = []; + const _advancedVars: RegistryVarsEntry[] = []; - if (packageInputStream.vars && packageInputStream.vars.length) { - packageInputStream.vars.forEach((varDef) => { - if (isAdvancedVar(varDef)) { - advancedVars.push(varDef); - } else { - requiredVars.push(varDef); - } - }); - } + if (packageInputStream.vars && packageInputStream.vars.length) { + packageInputStream.vars.forEach((varDef) => { + if (isAdvancedVar(varDef)) { + _advancedVars.push(varDef); + } else { + _requiredVars.push(varDef); + } + }); + } + + return [_requiredVars, _advancedVars]; + }, [packageInputStream.vars]); const advancedVarsWithErrorsCount: number = useMemo( () => @@ -135,7 +153,8 @@ export const PackagePolicyInputStreamConfig: React.FunctionComponent<{ ); })} - {advancedVars.length ? ( + {/* Advanced section */} + {(isPackagePolicyEdit || advancedVars.length) && ( @@ -165,8 +184,9 @@ export const PackagePolicyInputStreamConfig: React.FunctionComponent<{ ) : null} - {isShowingAdvanced - ? advancedVars.map((varDef) => { + {isShowingAdvanced ? ( + <> + {advancedVars.map((varDef) => { if (!packagePolicyInputStream.vars) return null; const { name: varName, type: varType } = varDef; const value = packagePolicyInputStream.vars?.[varName]?.value; @@ -192,10 +212,28 @@ export const PackagePolicyInputStreamConfig: React.FunctionComponent<{ /> ); - }) - : null} + })} + {/* Only show datastream pipelines and mappings on edit */} + {isPackagePolicyEdit && ( + <> + + + + + + + + )} + + ) : null} - ) : null} + )} diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/step_configure_package.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/step_configure_package.tsx index db70c4b480b02..57b5376c9fbb7 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/step_configure_package.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/step_configure_package.tsx @@ -72,6 +72,8 @@ export const StepConfigurePackagePolicy: React.FunctionComponent<{ ) => { diff --git a/x-pack/plugins/fleet/public/hooks/use_request/index.ts b/x-pack/plugins/fleet/public/hooks/use_request/index.ts index 2973d2dcd3fc8..2f700052acd7b 100644 --- a/x-pack/plugins/fleet/public/hooks/use_request/index.ts +++ b/x-pack/plugins/fleet/public/hooks/use_request/index.ts @@ -16,3 +16,4 @@ export * from './outputs'; export * from './settings'; export * from './setup'; export * from './app'; +export * from './ingest_pipelines'; diff --git a/x-pack/plugins/fleet/public/hooks/use_request/ingest_pipelines.ts b/x-pack/plugins/fleet/public/hooks/use_request/ingest_pipelines.ts new file mode 100644 index 0000000000000..c5bd3fed7d7fe --- /dev/null +++ b/x-pack/plugins/fleet/public/hooks/use_request/ingest_pipelines.ts @@ -0,0 +1,17 @@ +/* + * 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 { GetDataStreamsResponse } from '../../types'; + +import { useRequest } from './use_request'; + +export const useGetPipeline = (pipelineId: string) => { + return useRequest({ + path: `/api/ingest_pipelines/${pipelineId}`, + method: 'get', + }); +}; diff --git a/x-pack/plugins/fleet/public/index.ts b/x-pack/plugins/fleet/public/index.ts index 25714ead50a30..5f97cfa4d2740 100644 --- a/x-pack/plugins/fleet/public/index.ts +++ b/x-pack/plugins/fleet/public/index.ts @@ -26,3 +26,8 @@ export { pagePathGetters } from './constants'; export { pkgKeyFromPackageInfo } from './services'; export type { CustomAssetsAccordionProps } from './components/custom_assets_accordion'; export { CustomAssetsAccordion } from './components/custom_assets_accordion'; +// Export Package editor components for custom editors +export { PackagePolicyEditorDatastreamPipelines } from './applications/fleet/sections/agent_policy/create_package_policy_page/components/datastream_pipelines'; +export type { PackagePolicyEditorDatastreamPipelinesProps } from './applications/fleet/sections/agent_policy/create_package_policy_page/components/datastream_pipelines'; +export { PackagePolicyEditorDatastreamMappings } from './applications/fleet/sections/agent_policy/create_package_policy_page/components/datastream_mappings'; +export type { PackagePolicyEditorDatastreamMappingsProps } from './applications/fleet/sections/agent_policy/create_package_policy_page/components/datastream_mappings'; diff --git a/x-pack/plugins/fleet/server/constants/fleet_es_assets.ts b/x-pack/plugins/fleet/server/constants/fleet_es_assets.ts index 56aaf450d46e9..ded329ba79bab 100644 --- a/x-pack/plugins/fleet/server/constants/fleet_es_assets.ts +++ b/x-pack/plugins/fleet/server/constants/fleet_es_assets.ts @@ -9,10 +9,6 @@ import { getESAssetMetadata } from '../services/epm/elasticsearch/meta'; const meta = getESAssetMetadata(); -export const PACKAGE_TEMPLATE_SUFFIX = '@package'; - -export const USER_SETTINGS_TEMPLATE_SUFFIX = '@custom'; - export const FLEET_FINAL_PIPELINE_ID = '.fleet_final_pipeline-1'; export const FLEET_GLOBALS_COMPONENT_TEMPLATE_NAME = '.fleet_globals-1'; diff --git a/x-pack/plugins/fleet/server/constants/index.ts b/x-pack/plugins/fleet/server/constants/index.ts index ae7e5456efa16..11f44ab07896c 100644 --- a/x-pack/plugins/fleet/server/constants/index.ts +++ b/x-pack/plugins/fleet/server/constants/index.ts @@ -57,6 +57,9 @@ export { PRECONFIGURATION_DELETION_RECORD_SAVED_OBJECT_TYPE, PRECONFIGURATION_LATEST_KEYWORD, AUTO_UPDATE_PACKAGES, + // EPM + USER_SETTINGS_TEMPLATE_SUFFIX, + PACKAGE_TEMPLATE_SUFFIX, // Download sources DEFAULT_DOWNLOAD_SOURCE, DOWNLOAD_SOURCE_SAVED_OBJECT_TYPE, @@ -72,6 +75,4 @@ export { FLEET_FINAL_PIPELINE_ID, FLEET_FINAL_PIPELINE_CONTENT, FLEET_FINAL_PIPELINE_VERSION, - USER_SETTINGS_TEMPLATE_SUFFIX, - PACKAGE_TEMPLATE_SUFFIX, } from './fleet_es_assets'; diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/index.test.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/index.test.ts deleted file mode 100644 index fb89c117ae16b..0000000000000 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/index.test.ts +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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 { RegistryDataStream } from '../../../types'; - -import { getRegistryDataStreamAssetBaseName } from '.'; - -test('getBaseName', () => { - const dataStream: RegistryDataStream = { - dataset: 'nginx.access', - title: 'Nginx Acess Logs', - release: 'beta', - type: 'logs', - ingest_pipeline: 'default', - package: 'nginx', - path: 'access', - }; - const name = getRegistryDataStreamAssetBaseName(dataStream); - expect(name).toStrictEqual('logs-nginx.access'); -}); - -test('getBaseName for hidden index', () => { - const dataStream: RegistryDataStream = { - dataset: 'nginx.access', - title: 'Nginx Acess Logs', - release: 'beta', - type: 'logs', - ingest_pipeline: 'default', - package: 'nginx', - path: 'access', - hidden: true, - }; - const name = getRegistryDataStreamAssetBaseName(dataStream); - expect(name).toStrictEqual('.logs-nginx.access'); -}); diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/index.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/index.ts deleted file mode 100644 index 81e05ef7d6314..0000000000000 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* - * 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 { RegistryDataStream } from '../../../types'; - -/** - * Creates the base name for Elasticsearch assets in the form of - * {type}-{dataset} - */ -export function getRegistryDataStreamAssetBaseName(dataStream: RegistryDataStream): string { - const baseName = `${dataStream.type}-${dataStream.dataset}`; - return dataStream.hidden ? `.${baseName}` : baseName; -} diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/helpers.test.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/helpers.test.ts index 3699db0531db6..fcd60ec51e69e 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/helpers.test.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/helpers.test.ts @@ -12,7 +12,6 @@ import type { RegistryDataStream } from '../../../../types'; import { addCustomPipelineProcessor, - getCustomPipelineNameForDatastream, getPipelineNameForInstallation, rewriteIngestPipeline, } from './helpers'; @@ -192,14 +191,3 @@ processors: ); }); }); - -describe('getCustomPipelineNameForDatastream', () => { - it('return the correct custom pipeline for datastream', () => { - const res = getCustomPipelineNameForDatastream({ - type: 'logs', - dataset: 'test', - } as any); - - expect(res).toBe('logs-test@custom'); - }); -}); diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/helpers.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/helpers.ts index b2022bfdb8aa3..dc6e72ffe1b3f 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/helpers.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/helpers.ts @@ -10,6 +10,8 @@ import { ElasticsearchAssetType } from '../../../../types'; import type { RegistryDataStream } from '../../../../types'; import { getPathParts } from '../../archive'; +import { getPipelineNameForDatastream } from '../../../../../common'; + import type { PipelineInstall, RewriteSubstitution } from './types'; export const isTopLevelPipeline = (path: string) => { @@ -38,20 +40,6 @@ export const getPipelineNameForInstallation = ({ return `${packageVersion}-${pipelineName}`; }; -export const getPipelineNameForDatastream = ({ - dataStream, - packageVersion, -}: { - dataStream: RegistryDataStream; - packageVersion: string; -}): string => { - return `${dataStream.type}-${dataStream.dataset}-${packageVersion}`; -}; - -export const getCustomPipelineNameForDatastream = (dataStream: RegistryDataStream): string => { - return `${dataStream.type}-${dataStream.dataset}@custom`; -}; - export function rewriteIngestPipeline( pipeline: string, substitutions: RewriteSubstitution[] diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/index.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/index.ts index a8f0065645b66..0a8414b4959bf 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/index.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/index.ts @@ -6,5 +6,5 @@ */ export { prepareToInstallPipelines } from './install'; -export { getPipelineNameForDatastream, isTopLevelPipeline } from './helpers'; +export { isTopLevelPipeline } from './helpers'; export { deletePreviousPipelines, deletePipeline } from './remove'; diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/install.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/install.ts index 481d551cb07ac..a1fad104d82ef 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/install.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/install.ts @@ -17,13 +17,15 @@ import { FLEET_FINAL_PIPELINE_ID, FLEET_FINAL_PIPELINE_VERSION, } from '../../../../constants'; +import { + getCustomPipelineNameForDatastream, + getPipelineNameForDatastream, +} from '../../../../../common'; import { appendMetadataToIngestPipeline } from '../meta'; import { retryTransientEsErrors } from '../retry'; import { - getCustomPipelineNameForDatastream, - getPipelineNameForDatastream, getPipelineNameForInstallation, rewriteIngestPipeline, isTopLevelPipeline, diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.ts index 0393c8bf91a50..c0a185a0b270e 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.ts @@ -10,6 +10,7 @@ import Boom from '@hapi/boom'; import type { ElasticsearchClient, Logger } from '@kbn/core/server'; import { ElasticsearchAssetType } from '../../../../types'; +import { getPipelineNameForDatastream } from '../../../../../common'; import type { RegistryDataStream, IndexTemplateEntry, @@ -22,9 +23,7 @@ import type { EsAssetReference, PackageInfo, } from '../../../../types'; - import { loadFieldsFromYaml, processFields } from '../../fields/field'; -import { getPipelineNameForDatastream } from '../ingest_pipeline'; import { getAsset, getPathParts } from '../../archive'; import { FLEET_COMPONENT_TEMPLATES, diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/remove_legacy.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/remove_legacy.ts index 44b9756edc448..b89f5f8a7355a 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/remove_legacy.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/remove_legacy.ts @@ -12,7 +12,7 @@ import type { import type { ElasticsearchClient, Logger } from '@kbn/core/server'; import type { InstallablePackage, RegistryDataStream } from '../../../../types'; -import { getRegistryDataStreamAssetBaseName } from '..'; +import { getRegistryDataStreamAssetBaseName } from '../../../../../common'; const LEGACY_TEMPLATE_SUFFIXES = ['@mappings', '@settings']; const getComponentTemplateWithSuffix = (dataStream: RegistryDataStream, suffix: string) => { diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.ts index c87df0921e745..02c5508321db9 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.ts @@ -16,7 +16,7 @@ import type { IndexTemplateMappings, } from '../../../../types'; import { appContextService } from '../../..'; -import { getRegistryDataStreamAssetBaseName } from '..'; +import { getRegistryDataStreamAssetBaseName } from '../../../../../common'; import { FLEET_GLOBALS_COMPONENT_TEMPLATE_NAME, FLEET_AGENT_ID_VERIFY_COMPONENT_TEMPLATE_NAME,