-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[APM] Migrate to data streams - Fleet on Cloud (#102682)
* [APM] Adds migration to fleet-managed APM server in APM UI Settings (#100657) * adds useStrictParams option to apm server routes to allow unknown record type in param.bopy * Adds checks for required roles, policies, and config before allowing user to initiate migration * refactored and cleaned up server-side code * i18n and link to Fleet * fixes linting issues and unit tests * updates the apm package policy to 0.3.0 and adds some missing config mappings * PR feedback * Handles case where the cloud policy doesn't exist * Reverts the addition of the useStrictParams option since strictKeysRt now supports records * fixes default input var values and uses correct published package version * displays reasons the switch to data streams is disabled * Store apm-server schema with the internal saved objects client
- Loading branch information
Showing
21 changed files
with
1,179 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file added
BIN
+113 KB
x-pack/plugins/apm/public/components/app/Settings/schema/blog-rocket-720x420.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
143 changes: 143 additions & 0 deletions
143
x-pack/plugins/apm/public/components/app/Settings/schema/confirm_switch_modal.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
/* | ||
* 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, { useState } from 'react'; | ||
import { | ||
EuiConfirmModal, | ||
EuiCallOut, | ||
EuiCheckbox, | ||
EuiSpacer, | ||
EuiCodeBlock, | ||
htmlIdGenerator, | ||
} from '@elastic/eui'; | ||
import { i18n } from '@kbn/i18n'; | ||
import { ElasticDocsLink } from '../../../shared/Links/ElasticDocsLink'; | ||
|
||
interface Props { | ||
onConfirm: () => void; | ||
onCancel: () => void; | ||
unsupportedConfigs: Array<{ key: string; value: string }>; | ||
isLoading: boolean; | ||
} | ||
export function ConfirmSwitchModal({ | ||
onConfirm, | ||
onCancel, | ||
unsupportedConfigs, | ||
isLoading, | ||
}: Props) { | ||
const [isConfirmChecked, setIsConfirmChecked] = useState(false); | ||
const hasUnsupportedConfigs = !!unsupportedConfigs.length; | ||
return ( | ||
<EuiConfirmModal | ||
title={i18n.translate('xpack.apm.settings.schema.confirm.title', { | ||
defaultMessage: 'Please confirm your choice', | ||
})} | ||
cancelButtonText={i18n.translate( | ||
'xpack.apm.settings.schema.confirm.cancelText', | ||
{ | ||
defaultMessage: 'Cancel', | ||
} | ||
)} | ||
onCancel={onCancel} | ||
confirmButtonText={i18n.translate( | ||
'xpack.apm.settings.schema.confirm.switchButtonText', | ||
{ | ||
defaultMessage: 'Switch to data streams', | ||
} | ||
)} | ||
defaultFocusedButton="confirm" | ||
onConfirm={onConfirm} | ||
confirmButtonDisabled={!isConfirmChecked} | ||
isLoading={isLoading} | ||
> | ||
<p> | ||
{i18n.translate('xpack.apm.settings.schema.confirm.descriptionText', { | ||
defaultMessage: | ||
'If you have custom dashboards, machine learning jobs, or source maps that use classic APM indices, you must reconfigure them for data streams. Stack monitoring is not currently supported with Fleet-managed APM.', | ||
})} | ||
</p> | ||
{!hasUnsupportedConfigs && ( | ||
<p> | ||
{i18n.translate( | ||
'xpack.apm.settings.schema.confirm.unsupportedConfigs.descriptionText', | ||
{ | ||
defaultMessage: `Compatible custom apm-server.yml user settings will be moved to Fleet Server settings for you. We'll let you know which settings are incompatible before removing them.`, | ||
} | ||
)} | ||
</p> | ||
)} | ||
<EuiCallOut | ||
title={i18n.translate( | ||
'xpack.apm.settings.schema.confirm.irreversibleWarning.title', | ||
{ | ||
defaultMessage: `Switching to data streams is an irreversible action`, | ||
} | ||
)} | ||
color="warning" | ||
iconType="help" | ||
> | ||
<p> | ||
{i18n.translate( | ||
'xpack.apm.settings.schema.confirm.irreversibleWarning.message', | ||
{ | ||
defaultMessage: `It might temporarily affect your APM data collection while the migration is in progress. The process of migrating should only take a few minutes.`, | ||
} | ||
)} | ||
</p> | ||
</EuiCallOut> | ||
<EuiSpacer size="m" /> | ||
{hasUnsupportedConfigs && ( | ||
<> | ||
<EuiCallOut | ||
title={i18n.translate( | ||
'xpack.apm.settings.schema.confirm.unsupportedConfigs.title', | ||
{ | ||
defaultMessage: `The following apm-server.yml user settings are incompatible and will be removed`, | ||
} | ||
)} | ||
iconType="iInCircle" | ||
> | ||
<EuiCodeBlock language="yaml"> | ||
{unsupportedConfigs | ||
.map(({ key, value }) => `${key}: ${JSON.stringify(value)}`) | ||
.join('\n')} | ||
</EuiCodeBlock> | ||
<p> | ||
<ElasticDocsLink | ||
section="/cloud" | ||
path="/ec-manage-apm-settings.html" | ||
target="_blank" | ||
> | ||
{i18n.translate( | ||
'xpack.apm.settings.schema.confirm.apmServerSettingsCloudLinkText', | ||
{ defaultMessage: 'Go to APM Server settings in Cloud' } | ||
)} | ||
</ElasticDocsLink> | ||
</p> | ||
</EuiCallOut> | ||
<EuiSpacer size="m" /> | ||
</> | ||
)} | ||
<p> | ||
<EuiCheckbox | ||
id={htmlIdGenerator()()} | ||
label={i18n.translate( | ||
'xpack.apm.settings.schema.confirm.checkboxLabel', | ||
{ | ||
defaultMessage: `I confirm that I wish to switch to data streams`, | ||
} | ||
)} | ||
checked={isConfirmChecked} | ||
onChange={(e) => { | ||
setIsConfirmChecked(e.target.checked); | ||
}} | ||
disabled={isLoading} | ||
/> | ||
</p> | ||
</EuiConfirmModal> | ||
); | ||
} |
137 changes: 137 additions & 0 deletions
137
x-pack/plugins/apm/public/components/app/Settings/schema/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
/* | ||
* 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, { useState } from 'react'; | ||
import { i18n } from '@kbn/i18n'; | ||
import { NotificationsStart } from 'kibana/public'; | ||
import { SchemaOverview } from './schema_overview'; | ||
import { ConfirmSwitchModal } from './confirm_switch_modal'; | ||
import { FETCH_STATUS, useFetcher } from '../../../../hooks/use_fetcher'; | ||
import { | ||
callApmApi, | ||
APIReturnType, | ||
} from '../../../../services/rest/createCallApmApi'; | ||
import { useApmPluginContext } from '../../../../context/apm_plugin/use_apm_plugin_context'; | ||
|
||
type FleetMigrationCheckResponse = APIReturnType<'GET /api/apm/fleet/migration_check'>; | ||
|
||
export function Schema() { | ||
const { toasts } = useApmPluginContext().core.notifications; | ||
const [isSwitchActive, setIsSwitchActive] = useState(false); | ||
const [isLoadingMigration, setIsLoadingMigration] = useState(false); | ||
const [isLoadingConfirmation, setIsLoadingConfirmation] = useState(false); | ||
const [unsupportedConfigs, setUnsupportedConfigs] = useState< | ||
Array<{ key: string; value: any }> | ||
>([]); | ||
|
||
const { | ||
refetch, | ||
data = {} as FleetMigrationCheckResponse, | ||
status, | ||
} = useFetcher( | ||
(callApi) => callApi({ endpoint: 'GET /api/apm/fleet/migration_check' }), | ||
[], | ||
{ preservePreviousData: false } | ||
); | ||
const isLoading = status !== FETCH_STATUS.SUCCESS; | ||
const cloudApmMigrationEnabled = !!data.cloud_apm_migration_enabled; | ||
const hasCloudAgentPolicy = !!data.has_cloud_agent_policy; | ||
const hasCloudApmPackagePolicy = !!data.has_cloud_apm_package_policy; | ||
const hasRequiredRole = !!data.has_required_role; | ||
return ( | ||
<> | ||
<SchemaOverview | ||
onSwitch={async () => { | ||
setIsLoadingConfirmation(true); | ||
const unsupported = await getUnsupportedApmServerConfigs(toasts); | ||
if (!unsupported) { | ||
setIsLoadingConfirmation(false); | ||
return; | ||
} | ||
setUnsupportedConfigs(unsupported); | ||
setIsLoadingConfirmation(false); | ||
setIsSwitchActive(true); | ||
}} | ||
isMigrated={hasCloudApmPackagePolicy} | ||
isLoading={isLoading} | ||
isLoadingConfirmation={isLoadingConfirmation} | ||
cloudApmMigrationEnabled={cloudApmMigrationEnabled} | ||
hasCloudAgentPolicy={hasCloudAgentPolicy} | ||
hasRequiredRole={hasRequiredRole} | ||
/> | ||
{isSwitchActive && ( | ||
<ConfirmSwitchModal | ||
isLoading={isLoadingMigration} | ||
onConfirm={async () => { | ||
setIsLoadingMigration(true); | ||
const apmPackagePolicy = await createCloudApmPackagePolicy(toasts); | ||
if (!apmPackagePolicy) { | ||
setIsLoadingMigration(false); | ||
return; | ||
} | ||
setIsSwitchActive(false); | ||
refetch(); | ||
}} | ||
onCancel={() => { | ||
if (isLoadingMigration) { | ||
return; | ||
} | ||
setIsSwitchActive(false); | ||
}} | ||
unsupportedConfigs={unsupportedConfigs} | ||
/> | ||
)} | ||
</> | ||
); | ||
} | ||
|
||
async function getUnsupportedApmServerConfigs( | ||
toasts: NotificationsStart['toasts'] | ||
) { | ||
try { | ||
const { unsupported } = await callApmApi({ | ||
endpoint: 'GET /api/apm/fleet/apm_server_schema/unsupported', | ||
signal: null, | ||
}); | ||
return unsupported; | ||
} catch (error) { | ||
toasts.addDanger({ | ||
title: i18n.translate( | ||
'xpack.apm.settings.unsupportedConfigs.errorToast.title', | ||
{ | ||
defaultMessage: 'Unable to fetch APM Server settings', | ||
} | ||
), | ||
text: error.body?.message || error.message, | ||
}); | ||
} | ||
} | ||
|
||
async function createCloudApmPackagePolicy( | ||
toasts: NotificationsStart['toasts'] | ||
) { | ||
try { | ||
const { | ||
cloud_apm_package_policy: cloudApmPackagePolicy, | ||
} = await callApmApi({ | ||
endpoint: 'POST /api/apm/fleet/cloud_apm_package_policy', | ||
signal: null, | ||
}); | ||
return cloudApmPackagePolicy; | ||
} catch (error) { | ||
toasts.addDanger({ | ||
title: i18n.translate( | ||
'xpack.apm.settings.createApmPackagePolicy.errorToast.title', | ||
{ | ||
defaultMessage: | ||
'Unable to create APM package policy on cloud agent policy', | ||
} | ||
), | ||
text: error.body?.message || error.message, | ||
}); | ||
} | ||
} |
Oops, something went wrong.