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,