diff --git a/x-pack/plugins/ingest_manager/common/services/config_to_yaml.ts b/x-pack/plugins/ingest_manager/common/services/config_to_yaml.ts index c2043a40369e2..7e03e4572f9ee 100644 --- a/x-pack/plugins/ingest_manager/common/services/config_to_yaml.ts +++ b/x-pack/plugins/ingest_manager/common/services/config_to_yaml.ts @@ -11,8 +11,8 @@ const CONFIG_KEYS_ORDER = [ 'name', 'revision', 'type', - 'settings', 'outputs', + 'settings', 'inputs', 'enabled', 'use_output', diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_request/agent_config.ts b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_request/agent_config.ts index 56b78c6faa93a..0bb09c2731032 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_request/agent_config.ts +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_request/agent_config.ts @@ -48,6 +48,17 @@ export const useGetOneAgentConfigFull = (agentConfigId: string) => { }); }; +export const sendGetOneAgentConfigFull = ( + agentConfigId: string, + query: { standalone?: boolean } = {} +) => { + return sendRequest({ + path: agentConfigRouteService.getInfoFullPath(agentConfigId), + method: 'get', + query, + }); +}; + export const sendGetOneAgentConfig = (agentConfigId: string) => { return sendRequest({ path: agentConfigRouteService.getInfoPath(agentConfigId), diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_request/enrollment_api_keys.ts b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_request/enrollment_api_keys.ts index 10d9e03e986e1..5a334e2739027 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_request/enrollment_api_keys.ts +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_request/enrollment_api_keys.ts @@ -44,6 +44,18 @@ export function sendDeleteOneEnrollmentAPIKey(keyId: string, options?: RequestOp }); } +export function sendGetEnrollmentAPIKeys( + query: GetEnrollmentAPIKeysRequest['query'], + options?: RequestOptions +) { + return sendRequest({ + method: 'get', + path: enrollmentAPIKeyRouteService.getListPath(), + query, + ...options, + }); +} + export function useGetEnrollmentAPIKeys( query: GetEnrollmentAPIKeysRequest['query'], options?: RequestOptions diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/config_selection.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/config_selection.tsx index 8cd337586d1bc..6f53a237187e5 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/config_selection.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/config_selection.tsx @@ -4,46 +4,91 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { useState } from 'react'; +import React, { useState, useEffect } from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { EuiSelect, EuiSpacer, EuiText, EuiButtonEmpty } from '@elastic/eui'; -import { AgentConfig } from '../../../../types'; -import { useGetEnrollmentAPIKeys } from '../../../../hooks'; +import { AgentConfig, GetEnrollmentAPIKeysResponse } from '../../../../types'; +import { sendGetEnrollmentAPIKeys, useCore } from '../../../../hooks'; import { AgentConfigPackageBadges } from '../agent_config_package_badges'; -interface Props { +type Props = { agentConfigs: AgentConfig[]; - onKeyChange: (key: string) => void; -} + onConfigChange?: (key: string) => void; +} & ( + | { + withKeySelection: true; + onKeyChange?: (key: string) => void; + } + | { + withKeySelection: false; + } +); -export const EnrollmentStepAgentConfig: React.FC = ({ agentConfigs, onKeyChange }) => { - const [isAuthenticationSettingsOpen, setIsAuthenticationSettingsOpen] = useState(false); - const enrollmentAPIKeysRequest = useGetEnrollmentAPIKeys({ - page: 1, - perPage: 1000, - }); +export const EnrollmentStepAgentConfig: React.FC = (props) => { + const { notifications } = useCore(); + const { withKeySelection, agentConfigs, onConfigChange } = props; + const onKeyChange = props.withKeySelection && props.onKeyChange; + const [isAuthenticationSettingsOpen, setIsAuthenticationSettingsOpen] = useState(false); + const [enrollmentAPIKeys, setEnrollmentAPIKeys] = useState( + [] + ); const [selectedState, setSelectedState] = useState<{ agentConfigId?: string; enrollmentAPIKeyId?: string; }>({ agentConfigId: agentConfigs.length ? agentConfigs[0].id : undefined, }); - const filteredEnrollmentAPIKeys = React.useMemo(() => { - if (!selectedState.agentConfigId || !enrollmentAPIKeysRequest.data) { - return []; + + useEffect(() => { + if (onConfigChange && selectedState.agentConfigId) { + onConfigChange(selectedState.agentConfigId); } + }, [selectedState.agentConfigId, onConfigChange]); - return enrollmentAPIKeysRequest.data.list.filter( - (key) => key.config_id === selectedState.agentConfigId - ); - }, [enrollmentAPIKeysRequest.data, selectedState.agentConfigId]); + useEffect(() => { + if (!withKeySelection) { + return; + } + if (!selectedState.agentConfigId) { + setEnrollmentAPIKeys([]); + return; + } + + async function fetchEnrollmentAPIKeys() { + try { + const res = await sendGetEnrollmentAPIKeys({ + page: 1, + perPage: 10000, + }); + if (res.error) { + throw res.error; + } + + if (!res.data) { + throw new Error('No data while fetching enrollment API keys'); + } + + setEnrollmentAPIKeys( + res.data.list.filter((key) => key.config_id === selectedState.agentConfigId) + ); + } catch (error) { + notifications.toasts.addError(error, { + title: 'Error', + }); + } + } + fetchEnrollmentAPIKeys(); + }, [withKeySelection, selectedState.agentConfigId, notifications.toasts]); // Select first API key when config change React.useEffect(() => { - if (!selectedState.enrollmentAPIKeyId && filteredEnrollmentAPIKeys.length > 0) { - const enrollmentAPIKeyId = filteredEnrollmentAPIKeys[0].id; + if (!withKeySelection || !onKeyChange) { + return; + } + if (!selectedState.enrollmentAPIKeyId && enrollmentAPIKeys.length > 0) { + const enrollmentAPIKeyId = enrollmentAPIKeys[0].id; setSelectedState({ agentConfigId: selectedState.agentConfigId, enrollmentAPIKeyId, @@ -51,7 +96,7 @@ export const EnrollmentStepAgentConfig: React.FC = ({ agentConfigs, onKey onKeyChange(enrollmentAPIKeyId); } // eslint-disable-next-line react-hooks/exhaustive-deps - }, [filteredEnrollmentAPIKeys, selectedState.enrollmentAPIKeyId, selectedState.agentConfigId]); + }, [enrollmentAPIKeys, selectedState.enrollmentAPIKeyId, selectedState.agentConfigId]); return ( <> @@ -85,43 +130,47 @@ export const EnrollmentStepAgentConfig: React.FC = ({ agentConfigs, onKey {selectedState.agentConfigId && ( )} - - setIsAuthenticationSettingsOpen(!isAuthenticationSettingsOpen)} - > - - - {isAuthenticationSettingsOpen && ( + {withKeySelection && onKeyChange && ( <> - ({ - value: key.id, - text: key.name, - }))} - value={selectedState.enrollmentAPIKeyId || undefined} - prepend={ - - - - } - onChange={(e) => { - setSelectedState({ - ...selectedState, - enrollmentAPIKeyId: e.target.value, - }); - onKeyChange(e.target.value); - }} - /> + setIsAuthenticationSettingsOpen(!isAuthenticationSettingsOpen)} + > + + + {isAuthenticationSettingsOpen && ( + <> + + ({ + value: key.id, + text: key.name, + }))} + value={selectedState.enrollmentAPIKeyId || undefined} + prepend={ + + + + } + onChange={(e) => { + setSelectedState({ + ...selectedState, + enrollmentAPIKeyId: e.target.value, + }); + onKeyChange(e.target.value); + }} + /> + + )} )} diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/index.tsx index 43173124d6bae..5a9d3b7efe1bb 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/index.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/index.tsx @@ -14,23 +14,13 @@ import { EuiButtonEmpty, EuiButton, EuiFlyoutFooter, - EuiSteps, - EuiText, - EuiLink, + EuiTab, + EuiTabs, } from '@elastic/eui'; -import { EuiContainedStepProps } from '@elastic/eui/src/components/steps/steps'; -import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { AgentConfig } from '../../../../types'; -import { EnrollmentStepAgentConfig } from './config_selection'; -import { - useGetOneEnrollmentAPIKey, - useCore, - useGetSettings, - useLink, - useFleetStatus, -} from '../../../../hooks'; -import { ManualInstructions } from '../../../../components/enrollment_instructions'; +import { ManagedInstructions } from './managed_instructions'; +import { StandaloneInstructions } from './standalone_instructions'; interface Props { onClose: () => void; @@ -41,99 +31,40 @@ export const AgentEnrollmentFlyout: React.FunctionComponent = ({ onClose, agentConfigs = [], }) => { - const { getHref } = useLink(); - const core = useCore(); - const fleetStatus = useFleetStatus(); - - const [selectedAPIKeyId, setSelectedAPIKeyId] = useState(); - - const settings = useGetSettings(); - const apiKey = useGetOneEnrollmentAPIKey(selectedAPIKeyId); - - const kibanaUrl = - settings.data?.item?.kibana_url ?? `${window.location.origin}${core.http.basePath.get()}`; - const kibanaCASha256 = settings.data?.item?.kibana_ca_sha256; - - const steps: EuiContainedStepProps[] = [ - { - title: i18n.translate('xpack.ingestManager.agentEnrollment.stepDownloadAgentTitle', { - defaultMessage: 'Download the Elastic Agent', - }), - children: ( - - - - - ), - }} - /> - - ), - }, - { - title: i18n.translate('xpack.ingestManager.agentEnrollment.stepChooseAgentConfigTitle', { - defaultMessage: 'Choose an agent configuration', - }), - children: ( - - ), - }, - { - title: i18n.translate('xpack.ingestManager.agentEnrollment.stepRunAgentTitle', { - defaultMessage: 'Enroll and run the Elastic Agent', - }), - children: apiKey.data && ( - - ), - }, - ]; + const [mode, setMode] = useState<'managed' | 'standalone'>('managed'); return ( - +

+ + setMode('managed')}> + + + setMode('standalone')}> + + +
+ - {fleetStatus.isReady ? ( - <> - - + {mode === 'managed' ? ( + ) : ( - <> - - - - ), - }} - /> - + )} diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/managed_instructions.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/managed_instructions.tsx new file mode 100644 index 0000000000000..aabbd37e809a8 --- /dev/null +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/managed_instructions.tsx @@ -0,0 +1,91 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { useState } from 'react'; +import { EuiSteps, EuiLink, EuiText, EuiSpacer } from '@elastic/eui'; +import { EuiContainedStepProps } from '@elastic/eui/src/components/steps/steps'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { AgentConfig } from '../../../../types'; +import { + useGetOneEnrollmentAPIKey, + useCore, + useGetSettings, + useLink, + useFleetStatus, +} from '../../../../hooks'; +import { ManualInstructions } from '../../../../components/enrollment_instructions'; +import { DownloadStep, AgentConfigSelectionStep } from './steps'; + +interface Props { + agentConfigs: AgentConfig[]; +} + +export const ManagedInstructions: React.FunctionComponent = ({ agentConfigs = [] }) => { + const { getHref } = useLink(); + const core = useCore(); + const fleetStatus = useFleetStatus(); + + const [selectedAPIKeyId, setSelectedAPIKeyId] = useState(); + + const settings = useGetSettings(); + const apiKey = useGetOneEnrollmentAPIKey(selectedAPIKeyId); + + const kibanaUrl = + settings.data?.item?.kibana_url ?? `${window.location.origin}${core.http.basePath.get()}`; + const kibanaCASha256 = settings.data?.item?.kibana_ca_sha256; + + const steps: EuiContainedStepProps[] = [ + DownloadStep(), + AgentConfigSelectionStep({ agentConfigs, setSelectedAPIKeyId }), + { + title: i18n.translate('xpack.ingestManager.agentEnrollment.stepEnrollAndRunAgentTitle', { + defaultMessage: 'Enroll and start the Elastic Agent', + }), + children: apiKey.data && ( + + ), + }, + ]; + + return ( + <> + + + + + {fleetStatus.isReady ? ( + <> + + + ) : ( + <> + + + + ), + }} + /> + + )}{' '} + + ); +}; diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/standalone_instructions.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/standalone_instructions.tsx new file mode 100644 index 0000000000000..27f64059deb84 --- /dev/null +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/standalone_instructions.tsx @@ -0,0 +1,181 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { useState, useEffect, useMemo } from 'react'; +import { + EuiSteps, + EuiText, + EuiSpacer, + EuiButton, + EuiCode, + EuiFlexItem, + EuiFlexGroup, + EuiCodeBlock, + EuiCopy, +} from '@elastic/eui'; +import { EuiContainedStepProps } from '@elastic/eui/src/components/steps/steps'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { AgentConfig } from '../../../../types'; +import { useCore, sendGetOneAgentConfigFull } from '../../../../hooks'; +import { DownloadStep, AgentConfigSelectionStep } from './steps'; +import { configToYaml, agentConfigRouteService } from '../../../../services'; + +interface Props { + agentConfigs: AgentConfig[]; +} + +const RUN_INSTRUCTIONS = './elastic-agent run'; + +export const StandaloneInstructions: React.FunctionComponent = ({ agentConfigs = [] }) => { + const core = useCore(); + const { notifications } = core; + + const [selectedConfigId, setSelectedConfigId] = useState(); + const [fullAgentConfig, setFullAgentConfig] = useState(); + + const downloadLink = selectedConfigId + ? core.http.basePath.prepend( + `${agentConfigRouteService.getInfoFullDownloadPath(selectedConfigId)}?standalone=true` + ) + : undefined; + + useEffect(() => { + async function fetchFullConfig() { + try { + if (!selectedConfigId) { + return; + } + const res = await sendGetOneAgentConfigFull(selectedConfigId, { standalone: true }); + if (res.error) { + throw res.error; + } + + if (!res.data) { + throw new Error('No data while fetching full agent config'); + } + + setFullAgentConfig(res.data.item); + } catch (error) { + notifications.toasts.addError(error, { + title: 'Error', + }); + } + } + fetchFullConfig(); + }, [selectedConfigId, notifications.toasts]); + + const yaml = useMemo(() => configToYaml(fullAgentConfig), [fullAgentConfig]); + const steps: EuiContainedStepProps[] = [ + DownloadStep(), + AgentConfigSelectionStep({ agentConfigs, setSelectedConfigId }), + { + title: i18n.translate('xpack.ingestManager.agentEnrollment.stepConfigureAgentTitle', { + defaultMessage: 'Configure the agent', + }), + children: ( + <> + + elastic-agent.yml, + ESUsernameVariable: ES_USERNAME, + ESPasswordVariable: ES_PASSWORD, + outputSection: outputs, + }} + /> + + + + + {(copy) => ( + + + + )} + + + + + + + + + + + {yaml} + + + + ), + }, + { + title: i18n.translate('xpack.ingestManager.agentEnrollment.stepRunAgentTitle', { + defaultMessage: 'Start the agent', + }), + children: ( + <> + + + + {RUN_INSTRUCTIONS} + + + {(copy) => ( + + + + )} + + + + ), + }, + { + title: i18n.translate('xpack.ingestManager.agentEnrollment.stepCheckForDataTitle', { + defaultMessage: 'Check for data', + }), + status: 'incomplete', + children: ( + <> + + + + + ), + }, + ]; + + return ( + <> + + + + + + + ); +}; diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/steps.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/steps.tsx new file mode 100644 index 0000000000000..267f9027a094a --- /dev/null +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/steps.tsx @@ -0,0 +1,66 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { EuiText, EuiButton, EuiSpacer } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { i18n } from '@kbn/i18n'; +import { EnrollmentStepAgentConfig } from './config_selection'; +import { AgentConfig } from '../../../../types'; + +export const DownloadStep = () => { + return { + title: i18n.translate('xpack.ingestManager.agentEnrollment.stepDownloadAgentTitle', { + defaultMessage: 'Download the Elastic Agent', + }), + children: ( + <> + + + + + + + + + ), + }; +}; + +export const AgentConfigSelectionStep = ({ + agentConfigs, + setSelectedAPIKeyId, + setSelectedConfigId, +}: { + agentConfigs: AgentConfig[]; + setSelectedAPIKeyId?: (key: string) => void; + setSelectedConfigId?: (configId: string) => void; +}) => { + return { + title: i18n.translate('xpack.ingestManager.agentEnrollment.stepChooseAgentConfigTitle', { + defaultMessage: 'Choose an agent configuration', + }), + children: ( + + ), + }; +}; diff --git a/x-pack/plugins/ingest_manager/server/routes/agent_config/handlers.ts b/x-pack/plugins/ingest_manager/server/routes/agent_config/handlers.ts index 110f6b9950829..2aaf889296bd6 100644 --- a/x-pack/plugins/ingest_manager/server/routes/agent_config/handlers.ts +++ b/x-pack/plugins/ingest_manager/server/routes/agent_config/handlers.ts @@ -232,15 +232,17 @@ export const deleteAgentConfigsHandler: RequestHandler< } }; -export const getFullAgentConfig: RequestHandler> = async (context, request, response) => { +export const getFullAgentConfig: RequestHandler< + TypeOf, + TypeOf +> = async (context, request, response) => { const soClient = context.core.savedObjects.client; try { const fullAgentConfig = await agentConfigService.getFullConfig( soClient, - request.params.agentConfigId + request.params.agentConfigId, + { standalone: request.query.standalone === true } ); if (fullAgentConfig) { const body: GetFullAgentConfigResponse = { @@ -264,16 +266,19 @@ export const getFullAgentConfig: RequestHandler> = async (context, request, response) => { +export const downloadFullAgentConfig: RequestHandler< + TypeOf, + TypeOf +> = async (context, request, response) => { const soClient = context.core.savedObjects.client; const { params: { agentConfigId }, } = request; try { - const fullAgentConfig = await agentConfigService.getFullConfig(soClient, agentConfigId); + const fullAgentConfig = await agentConfigService.getFullConfig(soClient, agentConfigId, { + standalone: request.query.standalone === true, + }); if (fullAgentConfig) { const body = configToYaml(fullAgentConfig); const headers: ResponseHeaders = { diff --git a/x-pack/plugins/ingest_manager/server/services/agent_config.ts b/x-pack/plugins/ingest_manager/server/services/agent_config.ts index fe247d5b91db0..5f98c8881388d 100644 --- a/x-pack/plugins/ingest_manager/server/services/agent_config.ts +++ b/x-pack/plugins/ingest_manager/server/services/agent_config.ts @@ -365,7 +365,8 @@ class AgentConfigService { public async getFullConfig( soClient: SavedObjectsClientContract, - id: string + id: string, + options?: { standalone: boolean } ): Promise { let config; @@ -400,6 +401,13 @@ class AgentConfigService { api_key, ...outputConfig, }; + + if (options?.standalone) { + delete outputs[name].api_key; + outputs[name].username = 'ES_USERNAME'; + outputs[name].password = 'ES_PASSWORD'; + } + return outputs; }, {} as FullAgentConfig['outputs'] diff --git a/x-pack/plugins/ingest_manager/server/types/rest_spec/agent_config.ts b/x-pack/plugins/ingest_manager/server/types/rest_spec/agent_config.ts index d076a803f4b53..594bd141459c1 100644 --- a/x-pack/plugins/ingest_manager/server/types/rest_spec/agent_config.ts +++ b/x-pack/plugins/ingest_manager/server/types/rest_spec/agent_config.ts @@ -51,5 +51,6 @@ export const GetFullAgentConfigRequestSchema = { }), query: schema.object({ download: schema.maybe(schema.boolean()), + standalone: schema.maybe(schema.boolean()), }), }; diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index d5d7b1648e47f..a414e1e153729 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -8073,7 +8073,6 @@ "xpack.ingestManager.agentDetails.viewAgentListTitle": "すべてのエージェント構成を表示", "xpack.ingestManager.agentEnrollment.cancelButtonLabel": "キャンセル", "xpack.ingestManager.agentEnrollment.continueButtonLabel": "続行", - "xpack.ingestManager.agentEnrollment.downloadDescription": "ホストのコンピューターでElasticエージェントをダウンロードします。エージェントバイナリをダウンロードできます。検証署名はElasticの{downloadLink}にあります。", "xpack.ingestManager.agentEnrollment.downloadLink": "ダウンロードページ", "xpack.ingestManager.agentEnrollment.fleetNotInitializedText": "エージェントを登録する前に、フリートを設定する必要があります。{link}", "xpack.ingestManager.agentEnrollment.flyoutTitle": "新しいエージェントを登録", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index b22b89a40a774..7144b71750c5f 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -8077,7 +8077,6 @@ "xpack.ingestManager.agentDetails.viewAgentListTitle": "查看所有代理配置", "xpack.ingestManager.agentEnrollment.cancelButtonLabel": "取消", "xpack.ingestManager.agentEnrollment.continueButtonLabel": "继续", - "xpack.ingestManager.agentEnrollment.downloadDescription": "在主机计算机上下载 Elastic 代理。可以从 Elastic 的{downloadLink}下载代理二进制文件及其验证签名。", "xpack.ingestManager.agentEnrollment.downloadLink": "下载页面", "xpack.ingestManager.agentEnrollment.fleetNotInitializedText": "注册代理前需要设置 Fleet。{link}", "xpack.ingestManager.agentEnrollment.flyoutTitle": "注册新代理",