diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/hooks/navigation.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/hooks/navigation.tsx index 8b9ca7886d236..44302c8adcc2c 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/hooks/navigation.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/hooks/navigation.tsx @@ -28,11 +28,15 @@ interface UseCancelParams { } export const useCancelAddPackagePolicy = (params: UseCancelParams) => { - const { from, pkgkey, agentPolicyId } = params; + const { from, pkgkey: pkgkeyParam, agentPolicyId } = params; const { application: { navigateToApp }, } = useStartServices(); const routeState = useIntraAppState(); + const pkgkey = useMemo( + () => pkgkeyParam || routeState?.pkgkey, + [pkgkeyParam, routeState?.pkgkey] + ); const { getHref } = useLink(); const cancelClickHandler = useCallback( diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/index.tsx index e6e904d0ebba8..3cf6b362e7376 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/index.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/index.tsx @@ -15,11 +15,28 @@ import type { AddToPolicyParams, EditPackagePolicyFrom } from './types'; import { CreatePackagePolicySinglePage } from './single_page_layout'; import { CreatePackagePolicyMultiPage } from './multi_page_layout'; -export const CreatePackagePolicyPage: React.FC<{}> = () => { +export const CreatePackagePolicyPage: React.FC<{ + useMultiPageLayoutProp?: boolean; + originFrom?: EditPackagePolicyFrom; + propPolicyId?: string; + integrationName?: string; + setIntegrationStep?: (step: number) => void; + onCanceled?: () => void; +}> = ({ + useMultiPageLayoutProp, + originFrom, + propPolicyId, + integrationName, + setIntegrationStep, + onCanceled, +}) => { const { search } = useLocation(); const { params } = useRouteMatch(); const queryParams = useMemo(() => new URLSearchParams(search), [search]); - const useMultiPageLayout = useMemo(() => queryParams.has('useMultiPageLayout'), [queryParams]); + const useMultiPageLayout = useMemo( + () => useMultiPageLayoutProp ?? queryParams.has('useMultiPageLayout'), + [queryParams, useMultiPageLayoutProp] + ); const queryParamsPolicyId = useMemo( () => queryParams.get('policyId') ?? undefined, [queryParams] @@ -47,12 +64,16 @@ export const CreatePackagePolicyPage: React.FC<{}> = () => { * creation possible if a user has not chosen one from the packages UI. */ const from: EditPackagePolicyFrom = - 'policyId' in params || queryParamsPolicyId ? 'policy' : 'package'; + originFrom ?? ('policyId' in params || queryParamsPolicyId ? 'policy' : 'package'); const pageParams = { from, queryParamsPolicyId, + propPolicyId, + integrationName, prerelease, + setIntegrationStep, + onCanceled, }; if (useMultiPageLayout) { diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/multi_page_layout/components/multi_page_steps_layout.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/multi_page_layout/components/multi_page_steps_layout.tsx index 2ed48b4d3bb59..d9539e318c142 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/multi_page_layout/components/multi_page_steps_layout.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/multi_page_layout/components/multi_page_steps_layout.tsx @@ -64,7 +64,6 @@ export const MultiPageStepsLayout: React.FunctionComponent - {packageInfo && ( agentCount: enrolledAgentIds.length, showLoading: true, poll: commandCopied, + onClickViewAgents: () => { + onNext(); // Fixme: Wording does not match what it does. + }, }) ); diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/multi_page_layout/hooks/use_get_agent_policy_or_default.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/multi_page_layout/hooks/use_get_agent_policy_or_default.tsx index d46594ef6bb3b..ead4496b0ba7a 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/multi_page_layout/hooks/use_get_agent_policy_or_default.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/multi_page_layout/hooks/use_get_agent_policy_or_default.tsx @@ -5,8 +5,9 @@ * 2.0. */ -import { useEffect, useState, useMemo } from 'react'; +import { useEffect, useState, useMemo, useRef } from 'react'; import { i18n } from '@kbn/i18n'; +import { v4 as uuidv4 } from 'uuid'; import { generateNewAgentPolicyWithDefaults } from '../../../../../../../../common/services/generate_new_agent_policy'; diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/multi_page_layout/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/multi_page_layout/index.tsx index bc0cfc7adccf6..1d61e8e033358 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/multi_page_layout/index.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/multi_page_layout/index.tsx @@ -18,6 +18,12 @@ import { import type { AddToPolicyParams, CreatePackagePolicyParams } from '../types'; +import { useIntegrationsStateContext } from '../../../../../integrations/hooks'; + +import { CreatePackagePolicySinglePage } from '../single_page_layout'; + +import type { AgentPolicy } from '../../../../types'; + import { useGetAgentPolicyOrDefault } from './hooks'; import { @@ -42,6 +48,13 @@ const addIntegrationStep = { component: AddIntegrationPageStep, }; +const addIntegrationSingleLayoutStep = { + title: i18n.translate('xpack.fleet.createFirstPackagePolicy.addIntegrationStepTitle', { + defaultMessage: 'Add the integration', + }), + component: CreatePackagePolicySinglePage, +}; + const confirmDataStep = { title: i18n.translate('xpack.fleet.createFirstPackagePolicy.confirmDataStepTitle', { defaultMessage: 'Confirm incoming data', @@ -53,23 +66,35 @@ const fleetManagedSteps = [installAgentStep, addIntegrationStep, confirmDataStep const standaloneSteps = [addIntegrationStep, installAgentStep, confirmDataStep]; +const onboardingSteps = [addIntegrationSingleLayoutStep, installAgentStep, confirmDataStep]; + export const CreatePackagePolicyMultiPage: CreatePackagePolicyParams = ({ queryParamsPolicyId, prerelease, + from, + integrationName, + setIntegrationStep, + onCanceled, }) => { const { params } = useRouteMatch(); - const { pkgkey, policyId, integration } = params; + // fixme + const { pkgkey: pkgkeyParam, policyId, integration: integrationParam } = params; + const { pkgkey: pkgKeyContext } = useIntegrationsStateContext(); + const pkgkey = pkgkeyParam || pkgKeyContext; const { pkgName, pkgVersion } = splitPkgKey(pkgkey); - const [onSplash, setOnSplash] = useState(true); + const [onSplash, setOnSplash] = useState(from !== 'onboarding-integration'); const [currentStep, setCurrentStep] = useState(0); const [isManaged, setIsManaged] = useState(true); const { getHref } = useLink(); const [enrolledAgentIds, setEnrolledAgentIds] = useState([]); + const [selectedAgentPolicies, setSelectedAgentPolicies] = useState(); const toggleIsManaged = (newIsManaged: boolean) => { setIsManaged(newIsManaged); setCurrentStep(0); }; - const agentPolicyId = policyId || queryParamsPolicyId; + + const integration = integrationName || integrationParam; + const agentPolicyId = selectedAgentPolicies?.[0]?.id || policyId || queryParamsPolicyId; const { data: packageInfoData, error: packageInfoError, @@ -119,13 +144,23 @@ export const CreatePackagePolicyMultiPage: CreatePackagePolicyParams = ({ ); } - const steps = isManaged ? fleetManagedSteps : standaloneSteps; - const stepsNext = () => { + const steps = + from === 'onboarding-integration' + ? onboardingSteps + : isManaged + ? fleetManagedSteps + : standaloneSteps; + + const stepsNext = (props?: { selectedAgentPolicies: AgentPolicy[] }) => { if (currentStep === steps.length - 1) { return; } setCurrentStep(currentStep + 1); + setIntegrationStep(currentStep + 1); + if (props?.selectedAgentPolicies) { + setSelectedAgentPolicies(props?.selectedAgentPolicies); + } }; const stepsBack = () => { @@ -154,6 +189,7 @@ export const CreatePackagePolicyMultiPage: CreatePackagePolicyParams = ({ setIsManaged={toggleIsManaged} setEnrolledAgentIds={setEnrolledAgentIds} enrolledAgentIds={enrolledAgentIds} + onCanceled={onCanceled} /> ); }; diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/index.tsx index 3941c92a76c39..b206df51de00b 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/index.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/index.tsx @@ -76,6 +76,8 @@ import { generateNewAgentPolicyWithDefaults } from '../../../../../../../common/ import { packageHasAtLeastOneSecret } from '../utils'; +import { useIntegrationsStateContext } from '../../../../../integrations/hooks'; + import { CreatePackagePolicySinglePageLayout, PostInstallAddAgentModal } from './components'; import { useDevToolsRequest, useOnSubmit, useSetupTechnology } from './hooks'; import { PostInstallCloudFormationModal } from './components/cloud_security_posture/post_install_cloud_formation_modal'; @@ -105,12 +107,17 @@ export const CreatePackagePolicySinglePage: CreatePackagePolicyParams = ({ from, queryParamsPolicyId, prerelease, + onNext, + onCanceled, }) => { const { agents: { enabled: isFleetEnabled }, } = useConfig(); const hasFleetAddAgentsPrivileges = useAuthz().fleet.addAgents; const { params } = useRouteMatch(); + const { pkgkey: pkgKeyContext } = useIntegrationsStateContext(); + const pkgkey = params.pkgkey || pkgKeyContext; + const fleetStatus = useFleetStatus(); const { docLinks } = useStartServices(); const spaceSettings = useSpaceSettingsContext(); @@ -130,7 +137,7 @@ export const CreatePackagePolicySinglePage: CreatePackagePolicyParams = ({ queryParamsPolicyId ? SelectedPolicyTab.EXISTING : SelectedPolicyTab.NEW ); - const { pkgName, pkgVersion } = splitPkgKey(params.pkgkey); + const { pkgName, pkgVersion } = splitPkgKey(pkgkey); // Fetch package info const { data: packageInfoData, @@ -187,6 +194,24 @@ export const CreatePackagePolicySinglePage: CreatePackagePolicyParams = ({ hasFleetAddAgentsPrivileges, }); + const handleNavigateAddAgent = useCallback(() => { + if (onNext) { + onNext({ selectedAgentPolicies: agentPolicies }); + } else { + if (savedPackagePolicy) { + navigateAddAgent(savedPackagePolicy); + } + } + }, [onNext, agentPolicies, savedPackagePolicy, navigateAddAgent]); + + const handleCancellation = useCallback(() => { + if (onCanceled) { + onCanceled(); + } else { + navigateAddAgentHelp(savedPackagePolicy); + } + }, [onCanceled, savedPackagePolicy, navigateAddAgentHelp]); + const setPolicyValidation = useCallback( (selectedTab: SelectedPolicyTab, updatedAgentPolicy: NewAgentPolicy) => { if (selectedTab === SelectedPolicyTab.NEW) { @@ -230,7 +255,7 @@ export const CreatePackagePolicySinglePage: CreatePackagePolicyParams = ({ const { cancelClickHandler, cancelUrl } = useCancelAddPackagePolicy({ from, - pkgkey: params.pkgkey, + pkgkey, agentPolicyId: agentPolicyIds[0], }); useEffect(() => { @@ -504,7 +529,10 @@ export const CreatePackagePolicySinglePage: CreatePackagePolicyParams = ({ agentCount={agentCount} agentPolicies={agentPolicies} onConfirm={onSubmit} - onCancel={() => setFormState('VALID')} + onCancel={() => { + setFormState('VALID'); + onCanceled?.(); + }} /> )} {formState === 'SUBMITTED_NO_AGENTS' && @@ -513,8 +541,8 @@ export const CreatePackagePolicySinglePage: CreatePackagePolicyParams = ({ savedPackagePolicy && ( navigateAddAgent(savedPackagePolicy)} - onCancel={() => navigateAddAgentHelp(savedPackagePolicy)} + onConfirm={handleNavigateAddAgent} + onCancel={handleCancellation} /> )} {formState === 'SUBMITTED_AZURE_ARM_TEMPLATE' && @@ -523,8 +551,8 @@ export const CreatePackagePolicySinglePage: CreatePackagePolicyParams = ({ navigateAddAgent(savedPackagePolicy)} - onCancel={() => navigateAddAgentHelp(savedPackagePolicy)} + onConfirm={handleNavigateAddAgent} + onCancel={handleCancellation} /> )} {formState === 'SUBMITTED_CLOUD_FORMATION' && @@ -533,8 +561,8 @@ export const CreatePackagePolicySinglePage: CreatePackagePolicyParams = ({ navigateAddAgent(savedPackagePolicy)} - onCancel={() => navigateAddAgentHelp(savedPackagePolicy)} + onConfirm={handleNavigateAddAgent} + onCancel={handleCancellation} /> )} {formState === 'SUBMITTED_GOOGLE_CLOUD_SHELL' && @@ -543,8 +571,8 @@ export const CreatePackagePolicySinglePage: CreatePackagePolicyParams = ({ navigateAddAgent(savedPackagePolicy)} - onCancel={() => navigateAddAgentHelp(savedPackagePolicy)} + onConfirm={handleNavigateAddAgent} + onCancel={handleCancellation} /> )} {packageInfo && ( @@ -603,7 +631,12 @@ export const CreatePackagePolicySinglePage: CreatePackagePolicyParams = ({ - + {/* Only show render button bar in portal when enableRouts is false*/} + {packageInfo && (formState === 'INVALID' || hasAgentPolicyError) ? ( diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/types.ts b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/types.ts index 1a203c8bf2e60..ddb0229ffc56b 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/types.ts +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/types.ts @@ -13,7 +13,8 @@ export type EditPackagePolicyFrom = | 'edit' | 'upgrade-from-fleet-policy-list' | 'upgrade-from-integrations-policy-list' - | 'upgrade-from-extension'; + | 'upgrade-from-extension' + | 'onboarding-integration'; export type PackagePolicyFormState = | 'VALID' @@ -35,5 +36,8 @@ export interface AddToPolicyParams { export type CreatePackagePolicyParams = React.FunctionComponent<{ from: EditPackagePolicyFrom; queryParamsPolicyId?: string; + propPolicyId?: string; + integrationName?: string; prerelease: boolean; + onNext?: () => void; }>; diff --git a/x-pack/plugins/fleet/public/applications/integrations/app.tsx b/x-pack/plugins/fleet/public/applications/integrations/app.tsx index 8527dbc4c6c69..c2f310ec267cf 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/app.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/app.tsx @@ -38,7 +38,11 @@ import { INTEGRATIONS_ROUTING_PATHS, pagePathGetters } from './constants'; import type { UIExtensionsStorage } from './types'; import { EPMApp } from './sections/epm'; -import { PackageInstallProvider, UIExtensionsContext, FlyoutContextProvider } from './hooks'; +import { + PackageInstallProvider, + UIExtensionsContextProvider, + FlyoutContextProvider, +} from './hooks'; import { IntegrationsHeader } from './components/header'; import { AgentEnrollmentFlyout } from './components'; import { ReadOnlyContextProvider } from './hooks/use_read_only_context'; @@ -103,7 +107,7 @@ export const IntegrationsAppContext: React.FC<{ - + @@ -126,7 +130,7 @@ export const IntegrationsAppContext: React.FC<{ - + diff --git a/x-pack/plugins/fleet/public/applications/integrations/hooks/use_fleet_integration_context.tsx b/x-pack/plugins/fleet/public/applications/integrations/hooks/use_fleet_integration_context.tsx new file mode 100644 index 0000000000000..d4005439a39e8 --- /dev/null +++ b/x-pack/plugins/fleet/public/applications/integrations/hooks/use_fleet_integration_context.tsx @@ -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 React, { createContext } from 'react'; + +import { + FleetStatusProvider, + KibanaVersionContext, + UIExtensionsContextProvider, +} from '../../../hooks'; + +import type { FleetStartServices } from '../../../plugin'; + +import { PackageInstallProvider } from './use_package_install'; +import { IntegrationsStateContextProvider } from './use_integrations_state'; + +interface FleetIntegrationsStateContextValue { + pkgkey: string | undefined; + startServices: FleetStartServices | undefined; +} + +const FleetIntegrationsStateContext = createContext({ + pkgkey: undefined, + startServices: undefined, +}); + +export const FleetIntegrationsStateContextProvider: React.FC<{ + children?: React.ReactNode; + values: FleetIntegrationsStateContextValue; + /* fix hard coded KibanaVersion */ +}> = ({ children, values: { startServices, kibanaVersion = '8.16.0' } }) => { + return ( + + + + + + {children} + + + + + + ); +}; + +export const useFleetIntegrationsStateContext = () => { + const ctx = React.useContext(FleetIntegrationsStateContext); + if (!ctx) { + throw new Error( + 'useFleetIntegrationsStateContext can only be used inside of FleetIntegrationsStateContextProvider' + ); + } + return ctx; +}; diff --git a/x-pack/plugins/fleet/public/applications/integrations/hooks/use_integrations_state.tsx b/x-pack/plugins/fleet/public/applications/integrations/hooks/use_integrations_state.tsx index 9e4241a6e7f72..47243f2b30e30 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/hooks/use_integrations_state.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/hooks/use_integrations_state.tsx @@ -23,13 +23,19 @@ export const IntegrationsStateContextProvider: FunctionComponent<{ children?: React.ReactNode; }> = ({ children }) => { const maybeState = useIntraAppState(); - const fromIntegrationsRef = useRef(maybeState?.fromIntegrations); - + const stateRef = useRef(maybeState); + console.log('myState---', maybeState); const getFromIntegrations = useCallback(() => { - return fromIntegrationsRef.current; + return stateRef.current?.fromIntegrations; }, []); return ( - + {children} ); diff --git a/x-pack/plugins/fleet/public/applications/integrations/hooks/use_package_install.tsx b/x-pack/plugins/fleet/public/applications/integrations/hooks/use_package_install.tsx index 579a711a36398..e7226c23d9060 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/hooks/use_package_install.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/hooks/use_package_install.tsx @@ -261,16 +261,18 @@ function usePackageInstall({ startServices }: { startServices: StartServices }) }; } -export const [ - PackageInstallProvider, - useInstallPackage, - useSetPackageInstallStatus, - useGetPackageInstallStatus, - useUninstallPackage, -] = createContainer( +export const packageInstallContainer = createContainer( usePackageInstall, (value) => value.installPackage, (value) => value.setPackageInstallStatus, (value) => value.getPackageInstallStatus, (value) => value.uninstallPackage ); + +export const [ + PackageInstallProvider, + useInstallPackage, + useSetPackageInstallStatus, + useGetPackageInstallStatus, + useUninstallPackage, +] = packageInstallContainer; diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/components/add_integration_button.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/components/add_integration_button.tsx index 8ff7f3e7d5ec3..12aba97247775 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/components/add_integration_button.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/components/add_integration_button.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React from 'react'; +import React, { useMemo } from 'react'; import { FormattedMessage } from '@kbn/i18n-react'; import { EuiButtonWithTooltip } from '../../../../../components'; @@ -14,8 +14,8 @@ interface AddIntegrationButtonProps { userCanInstallPackages?: boolean; missingSecurityConfiguration: boolean; packageName: string; - href: string; - onClick: Function; + href: string | undefined; + onClick: Function | undefined; } export function AddIntegrationButton(props: AddIntegrationButtonProps) { @@ -38,15 +38,22 @@ export function AddIntegrationButton(props: AddIntegrationButtonProps) { } : undefined; + const optionalProps = useMemo( + () => ({ + ...(href ? { href } : {}), + ...(onClick ? { onClick: (e: React.MouseEvent) => onClick(e) } : {}), + }), + [href, onClick] + ); + return ( onClick(e)} data-test-subj="addIntegrationPolicyButton" tooltip={tooltip} + {...optionalProps} > void; +}) { const { getId: getAgentPolicyId } = useAgentPolicyContext(); - const { getFromIntegrations } = useIntegrationsStateContext(); - const { pkgkey, panel } = useParams(); + const { + getFromIntegrations, + pkgkey: pkgKeyContext, + panel: panelContext, + } = useIntegrationsStateContext(); + const [selectedPanel, setSelectedPanel] = useState(panelContext); + const { pkgkey: pkgkeyParam, panel: panelParam } = useParams(); + const pkgkey = pkgkeyParam || pkgKeyContext; + const panel = panelParam || selectedPanel; const { getHref, getPath } = useLink(); const history = useHistory(); const { pathname, search, hash } = useLocation(); @@ -144,7 +160,6 @@ export function Detail() { */ const onboardingLink = useMemo(() => queryParams.get('onboardingLink'), [queryParams]); const onboardingAppId = useMemo(() => queryParams.get('onboardingAppId'), [queryParams]); - const authz = useAuthz(); const canAddAgent = authz.fleet.addAgents; const canInstallPackages = authz.integrations.installPackages; @@ -178,7 +193,7 @@ export function Detail() { if (packageInfo === null || !packageInfo.name) { return undefined; } - return getPackageInstallStatus(packageInfo?.name)?.status; + return getPackageInstallStatus?.(packageInfo?.name)?.status; }, [packageInfo, getPackageInstallStatus]); const isInstalled = useMemo( () => @@ -401,6 +416,11 @@ export function Detail() { ev.preventDefault(); // The object below, given to `createHref` is explicitly accessing keys of `location` in order // to ensure that dependencies to this `useCallback` is set correctly (because `location` is mutable) + if (onAddIntegrationPolicyClick) { + onAddIntegrationPolicyClick(); + return; + } + const currentPath = history.createHref({ pathname, search, @@ -448,6 +468,7 @@ export function Detail() { isExperimentalAddIntegrationPageEnabled, isFirstTimeAgentUser, isGuidedOnboardingActive, + onAddIntegrationPolicyClick, onboardingAppId, onboardingLink, pathname, @@ -559,13 +580,17 @@ export function Detail() { > ) => { + e.preventDefault(); + setSelectedPanel('overview'); + }, }, ]; @@ -647,10 +680,16 @@ export function Detail() { ), isSelected: panel === 'policies', 'data-test-subj': `tab-policies`, - href: getHref('integration_details_policies', { - pkgkey: packageInfoKey, - ...(integration ? { integration } : {}), - }), + href: routesEnabled + ? getHref('integration_details_policies', { + pkgkey: packageInfoKey, + ...(integration ? { integration } : {}), + }) + : undefined, + onClick: (e: React.MouseEvent) => { + e.preventDefault(); + setSelectedPanel('policies'); + }, }); } @@ -671,10 +710,16 @@ export function Detail() { ), isSelected: panel === 'assets', 'data-test-subj': `tab-assets`, - href: getHref('integration_details_assets', { - pkgkey: packageInfoKey, - ...(integration ? { integration } : {}), - }), + href: routesEnabled + ? getHref('integration_details_assets', { + pkgkey: packageInfoKey, + ...(integration ? { integration } : {}), + }) + : undefined, + onClick: (e: React.MouseEvent) => { + e.preventDefault(); + setSelectedPanel('assets'); + }, }); } @@ -689,10 +734,16 @@ export function Detail() { ), isSelected: panel === 'settings', 'data-test-subj': `tab-settings`, - href: getHref('integration_details_settings', { - pkgkey: packageInfoKey, - ...(integration ? { integration } : {}), - }), + href: routesEnabled + ? getHref('integration_details_settings', { + pkgkey: packageInfoKey, + ...(integration ? { integration } : {}), + }) + : undefined, + onClick: (e: React.MouseEvent) => { + e.preventDefault(); + setSelectedPanel('settings'); + }, }); } @@ -707,10 +758,16 @@ export function Detail() { ), isSelected: panel === 'configs', 'data-test-subj': `tab-configs`, - href: getHref('integration_details_configs', { - pkgkey: packageInfoKey, - ...(integration ? { integration } : {}), - }), + href: routesEnabled + ? getHref('integration_details_configs', { + pkgkey: packageInfoKey, + ...(integration ? { integration } : {}), + }) + : undefined, + onClick: (e: React.MouseEvent) => { + e.preventDefault(); + setSelectedPanel('configs'); + }, }); } @@ -725,10 +782,16 @@ export function Detail() { ), isSelected: panel === 'custom', 'data-test-subj': `tab-custom`, - href: getHref('integration_details_custom', { - pkgkey: packageInfoKey, - ...(integration ? { integration } : {}), - }), + href: routesEnabled + ? getHref('integration_details_custom', { + pkgkey: packageInfoKey, + ...(integration ? { integration } : {}), + }) + : undefined, + onClick: (e: React.MouseEvent) => { + e.preventDefault(); + setSelectedPanel('custom'); + }, }); } @@ -743,10 +806,16 @@ export function Detail() { ), isSelected: panel === 'api-reference', 'data-test-subj': `tab-api-reference`, - href: getHref('integration_details_api_reference', { - pkgkey: packageInfoKey, - ...(integration ? { integration } : {}), - }), + href: routesEnabled + ? getHref('integration_details_api_reference', { + pkgkey: packageInfoKey, + ...(integration ? { integration } : {}), + }) + : undefined, + onClick: (e: React.MouseEvent) => { + e.preventDefault(); + setSelectedPanel('api-reference'); + }, }); } @@ -754,6 +823,7 @@ export function Detail() { }, [ packageInfo, panel, + originFrom, getHref, integration, canReadIntegrationPolicies, @@ -763,6 +833,7 @@ export function Detail() { showConfigTab, showCustomTab, showDocumentationTab, + routesEnabled, numOfDeferredInstallations, ]); @@ -823,45 +894,17 @@ export function Detail() { ) : isLoading || !packageInfo ? ( ) : ( - - - - - - - - - - - - - - - {canReadIntegrationPolicies ? ( - - ) : ( - - )} - - - - - - - - - + )} ); diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/settings/uninstall_button.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/settings/uninstall_button.tsx index aba40aeba2397..102c95e455069 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/settings/uninstall_button.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/settings/uninstall_button.tsx @@ -12,7 +12,12 @@ import { FormattedMessage } from '@kbn/i18n-react'; import { InstallStatus } from '../../../../../types'; import type { PackageInfo } from '../../../../../types'; -import { useAuthz, useGetPackageInstallStatus, useUninstallPackage } from '../../../../../hooks'; +import { + useAuthz, + useGetPackageInstallStatus, + useIntegrationsStateContext, + useUninstallPackage, +} from '../../../../../hooks'; import { ConfirmPackageUninstall } from './confirm_package_uninstall'; diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/tabs_content.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/tabs_content.tsx new file mode 100644 index 0000000000000..9559a4f969b2f --- /dev/null +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/tabs_content.tsx @@ -0,0 +1,112 @@ +/* + * 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 { Routes, Route } from '@kbn/shared-ux-router'; +import { Redirect } from 'react-router-dom'; + +import { INTEGRATIONS_ROUTING_PATHS } from '../../../../constants'; +import { PermissionsError } from '../../../../../fleet/layouts'; + +import type { FleetStart, FleetStartServices } from '../../../../../../plugin'; + +import { AssetsPage } from './assets'; +import { OverviewPage } from './overview'; +import { PackagePoliciesPage } from './policies'; +import { SettingsPage } from './settings'; +import { CustomViewPage } from './custom'; +import { DocumentationPage } from './documentation'; +import { Configs } from './configs'; + +export const TabsContent: React.FC<{ + canReadIntegrationPolicies: boolean; + integrationInfo: any; + latestGAVersion: string | undefined; + packageInfo: any; + packageInfoData: any; + panel: string; + refetchPackageInfo: () => void; + routesEnabled: boolean; + services: FleetStartServices & { + fleet?: FleetStart | undefined; + }; +}> = ({ + canReadIntegrationPolicies, + integrationInfo, + latestGAVersion, + packageInfo, + packageInfoData, + panel, + refetchPackageInfo, + routesEnabled, + services, +}) => { + const routesMap = { + overview: { + path: INTEGRATIONS_ROUTING_PATHS.integration_details_overview, + component: ( + + ), + }, + settings: { + path: INTEGRATIONS_ROUTING_PATHS.integration_details_settings, + component: ( + + ), + }, + assets: { + path: INTEGRATIONS_ROUTING_PATHS.integration_details_assets, + component: , + }, + configs: { + path: INTEGRATIONS_ROUTING_PATHS.integration_details_configs, + component: , + }, + policies: { + path: INTEGRATIONS_ROUTING_PATHS.integration_details_policies, + component: canReadIntegrationPolicies ? ( + + ) : ( + + ), + }, + custom: { + path: INTEGRATIONS_ROUTING_PATHS.integration_details_custom, + component: , + }, + apiReference: { + path: INTEGRATIONS_ROUTING_PATHS.integration_details_api_reference, + component: ( + + ), + }, + }; + return routesEnabled ? ( + + {Object.values(routesMap).map(({ path, component }) => ( + + {component} + + ))} + + + ) : ( + routesMap[panel].component + ); +}; + +TabsContent.displayName = 'TabsRoute'; diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/home/card_utils.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/home/card_utils.tsx index 19f4d8740b75d..260c231995ed7 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/home/card_utils.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/home/card_utils.tsx @@ -66,6 +66,7 @@ export interface IntegrationCardItem { url: string; version: string; type?: string; + pkgkey?: string; } export const mapToCard = ({ @@ -91,6 +92,9 @@ export const mapToCard = ({ let isUpdateAvailable = false; let isReauthorizationRequired = false; + + const pkgkey = item.name ? `${item.name}-${version}` : undefined; + if (item.type === 'ui_link') { uiInternalPathUrl = item.id.includes('language_client.') ? addBasePath(item.uiInternalPath) @@ -103,9 +107,8 @@ export const mapToCard = ({ isReauthorizationRequired = hasDeferredInstallations(item); } - const url = getHref('integration_details_overview', { - pkgkey: `${item.name}-${version}`, + pkgkey, ...(item.integration ? { integration: item.integration } : {}), }); @@ -136,6 +139,7 @@ export const mapToCard = ({ isUnverified, isUpdateAvailable, extraLabelsBadges, + pkgkey, }; if (item.type === 'integration') { diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/confirm_agent_enrollment.tsx b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/confirm_agent_enrollment.tsx index 53448aefd44c6..f067351546bde 100644 --- a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/confirm_agent_enrollment.tsx +++ b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/confirm_agent_enrollment.tsx @@ -116,9 +116,12 @@ export const ConfirmAgentEnrollment: React.FunctionComponent = ({ ); const onButtonClick = () => { - if (onClickViewAgents) onClickViewAgents(); - const href = getHref('agent_list'); - application.navigateToUrl(href); + if (onClickViewAgents) { + onClickViewAgents(); + } else { + const href = getHref('agent_list'); + application.navigateToUrl(href); + } }; if (!policyId || (agentCount === 0 && !showLoading)) { diff --git a/x-pack/plugins/fleet/public/hooks/use_authz.ts b/x-pack/plugins/fleet/public/hooks/use_authz.ts index c7a177c34dce1..14a1e74388f94 100644 --- a/x-pack/plugins/fleet/public/hooks/use_authz.ts +++ b/x-pack/plugins/fleet/public/hooks/use_authz.ts @@ -5,10 +5,13 @@ * 2.0. */ +import { useFleetIntegrationsStateContext } from '../applications/integrations/hooks/use_fleet_integration_context'; + import { useStartServices } from './use_core'; // Expose authz object, containing the privileges for Fleet and Integrations export function useAuthz() { const core = useStartServices(); - return core.authz; + const { fleet } = useFleetIntegrationsStateContext(); + return core.authz ?? fleet.authz; } diff --git a/x-pack/plugins/fleet/public/hooks/use_intra_app_state.tsx b/x-pack/plugins/fleet/public/hooks/use_intra_app_state.tsx index 265d12221018a..501777bac4d11 100644 --- a/x-pack/plugins/fleet/public/hooks/use_intra_app_state.tsx +++ b/x-pack/plugins/fleet/public/hooks/use_intra_app_state.tsx @@ -16,6 +16,5 @@ import type { AnyIntraAppRouteState } from '../types'; */ export function useIntraAppState(): S | undefined { const location = useLocation(); - return location.state as S; } diff --git a/x-pack/plugins/fleet/public/hooks/use_ui_extension.ts b/x-pack/plugins/fleet/public/hooks/use_ui_extension.tsx similarity index 82% rename from x-pack/plugins/fleet/public/hooks/use_ui_extension.ts rename to x-pack/plugins/fleet/public/hooks/use_ui_extension.tsx index 93e316be241cb..117cb778c21b1 100644 --- a/x-pack/plugins/fleet/public/hooks/use_ui_extension.ts +++ b/x-pack/plugins/fleet/public/hooks/use_ui_extension.tsx @@ -11,6 +11,16 @@ import type { UIExtensionPoint, UIExtensionsStorage } from '../types'; export const UIExtensionsContext = React.createContext({}); +export const UIExtensionsContextProvider = ({ + values, + children, +}: { + values: UIExtensionsStorage; + children: React.ReactNode; +}) => { + return {children}; +}; + type NarrowExtensionPoint = A extends { view: V; } diff --git a/x-pack/plugins/fleet/public/index.ts b/x-pack/plugins/fleet/public/index.ts index d82e9c88b7db8..eea00d893c9d1 100644 --- a/x-pack/plugins/fleet/public/index.ts +++ b/x-pack/plugins/fleet/public/index.ts @@ -10,6 +10,7 @@ import type { PluginInitializerContext } from '@kbn/core/public'; import { lazy } from 'react'; import { FleetPlugin } from './plugin'; +import type { UIExtensionsStorage } from './types'; export type { GetPackagesResponse } from './types'; export { installationStatuses } from '../common/constants'; @@ -89,3 +90,17 @@ export const AvailablePackagesHook = () => { './applications/integrations/sections/epm/screens/home/hooks/use_available_packages' ); }; +export const Detail = () => { + return import('./applications/integrations/sections/epm/screens/detail'); +}; +export const UseIntegrationsState = () => { + return import('./applications/integrations/hooks/use_integrations_state'); +}; + +export const CreatePackagePolicyPage = () => { + return import('./applications/fleet/sections/agent_policy/create_package_policy_page'); +}; + +export const FleetIntegrationsStateContextProvider = () => { + return import('./applications/integrations/hooks/use_fleet_integration_context'); +}; diff --git a/x-pack/plugins/security_solution/public/onboarding/components/onboarding.tsx b/x-pack/plugins/security_solution/public/onboarding/components/onboarding.tsx index caa0d9f9b79d7..664d5ed13872b 100644 --- a/x-pack/plugins/security_solution/public/onboarding/components/onboarding.tsx +++ b/x-pack/plugins/security_solution/public/onboarding/components/onboarding.tsx @@ -20,12 +20,14 @@ import { OnboardingContextProvider } from './onboarding_context'; import { OnboardingAVCBanner } from './onboarding_banner'; import { OnboardingRoute } from './onboarding_route'; import { OnboardingFooter } from './onboarding_footer'; +import type { StartPlugins } from '../../types'; const topicPathParam = `:topicId(${Object.values(OnboardingTopicId) // any topics .filter((val) => val !== OnboardingTopicId.default) // except "default" .join('|')})?`; // optional parameter -export const OnboardingPage = React.memo(() => { + +export const OnboardingPage = React.memo((plugins: StartPlugins) => { const spaceId = useSpaceId(); const { euiTheme } = useEuiTheme(); @@ -38,7 +40,7 @@ export const OnboardingPage = React.memo(() => { } return ( - + ({ .then((pkg) => pkg.PackageListGrid), })); +const Detail = lazy(async () => ({ + default: await import('@kbn/fleet-plugin/public') + .then((module) => module.Detail()) + .then((pkg) => pkg.Detail), +})); + +const CreatePackagePolicyPage = lazy(async () => ({ + default: await import('@kbn/fleet-plugin/public') + .then((module) => module.CreatePackagePolicyPage()) + .then((pkg) => pkg.CreatePackagePolicyPage), +})); + +const FleetIntegrationsStateContextProvider = lazy(async () => ({ + default: await import('@kbn/fleet-plugin/public') + .then((module) => module.FleetIntegrationsStateContextProvider()) + .then((pkg) => pkg.FleetIntegrationsStateContextProvider), +})); + +const integrationStepMap = { + 0: 'Add integration', + 1: 'Install Elastic Agent', + 2: 'Confirm incoming data', +} + export const IntegrationsCardGridTabsComponent = React.memo( ({ installedIntegrationsCount, isAgentRequired, useAvailablePackages }) => { const { spaceId } = useOnboardingContext(); + const startServices = useKibana().services; + const { + services: { fleet }, + } = useKibana(); const scrollElement = useRef(null); const [toggleIdSelected, setSelectedTabIdToStorage] = useStoredIntegrationTabId( spaceId, @@ -65,6 +107,25 @@ export const IntegrationsCardGridTabsComponent = React.memo( + 'overview' + ); + const [integrationStep, setIntegrationStep] = useState(0); + const onAddIntegrationPolicyClick = useCallback(() => { + setModalView('configure-integration'); + }, []); + const closeModal = useCallback(() => { + setIsModalVisible(false); + setModalView('overview'); + setIntegrationStep(0); + }, []); + const onCardClicked = useCallback((name: string) => { + setIsModalVisible(true); + setIntegrationName(name); + }, []); + const modalTitleId = useGeneratedHtmlId(); const { filteredCards, isLoading, @@ -77,7 +138,6 @@ export const IntegrationsCardGridTabsComponent = React.memo INTEGRATION_TABS_BY_ID[toggleIdSelected], [toggleIdSelected]); - const onSearchTermChanged = useCallback( (searchQuery: string) => { setSearchTerm(searchQuery); @@ -116,10 +176,10 @@ export const IntegrationsCardGridTabsComponent = React.memo - - - - + - } - > - - } - calloutTopSpacerSize="m" - categories={SEARCH_FILTER_CATEGORIES} // We do not want to show categories and subcategories as the search bar filter - emptyStateStyles={emptyStateStyles} - list={list} - scrollElementId={SCROLL_ELEMENT_ID} - searchTerm={searchTerm} - selectedCategory={selectedTab.category ?? ''} - selectedSubCategory={selectedTab.subCategory} - setCategory={setCategory} - setSearchTerm={onSearchTermChanged} - setUrlandPushHistory={noop} - setUrlandReplaceHistory={noop} - showCardLabels={false} - showControls={false} - showSearchTools={selectedTab.showSearchTools} - sortByFeaturedIntegrations={selectedTab.sortByFeaturedIntegrations} - spacer={false} + + - - - + + + } + > + + } + calloutTopSpacerSize="m" + categories={SEARCH_FILTER_CATEGORIES} // We do not want to show categories and subcategories as the search bar filter + emptyStateStyles={emptyStateStyles} + list={list} + scrollElementId={SCROLL_ELEMENT_ID} + searchTerm={searchTerm} + selectedCategory={selectedTab.category ?? ''} + selectedSubCategory={selectedTab.subCategory} + setCategory={setCategory} + setSearchTerm={onSearchTermChanged} + setUrlandPushHistory={noop} + setUrlandReplaceHistory={noop} + showCardLabels={false} + showControls={false} + showSearchTools={selectedTab.showSearchTools} + sortByFeaturedIntegrations={selectedTab.sortByFeaturedIntegrations} + spacer={false} + /> + + + + {isModalVisible && fleet && ( + + + {modalView === 'configure-integration' && ({`step indicator place holder. Integration step: ${integrationStepMap[integrationStep]}`})} + + + {modalView === 'overview' && ( + + )} + {modalView === 'configure-integration' && ( + + )} + + + {/* Close */} + + + )} + ); } ); diff --git a/x-pack/plugins/security_solution/public/onboarding/components/onboarding_body/cards/integrations/use_integration_card_list.ts b/x-pack/plugins/security_solution/public/onboarding/components/onboarding_body/cards/integrations/use_integration_card_list.ts index 660464ba73501..0af94c763f7f1 100644 --- a/x-pack/plugins/security_solution/public/onboarding/components/onboarding_body/cards/integrations/use_integration_card_list.ts +++ b/x-pack/plugins/security_solution/public/onboarding/components/onboarding_body/cards/integrations/use_integration_card_list.ts @@ -16,7 +16,6 @@ import { import { CARD_DESCRIPTION_LINE_CLAMP, CARD_TITLE_LINE_CLAMP, - INTEGRATION_APP_ID, MAX_CARD_HEIGHT_IN_PX, ONBOARDING_APP_ID, ONBOARDING_LINK, @@ -50,15 +49,23 @@ const getFilteredCards = ({ installedIntegrationList, integrationsList, navigateTo, + onCardClicked, }: { featuredCardIds?: string[]; getAppUrl: GetAppUrl; installedIntegrationList?: IntegrationCardItem[]; integrationsList: IntegrationCardItem[]; navigateTo: NavigateTo; + onCardClicked?: (integrationName: string) => void; }) => { const securityIntegrationsList = integrationsList.map((card) => - addSecuritySpecificProps({ navigateTo, getAppUrl, card, installedIntegrationList }) + addSecuritySpecificProps({ + navigateTo, + getAppUrl, + card, + installedIntegrationList, + onCardClicked, + }) ); if (!featuredCardIds) { return { featuredCards: [], integrationCards: securityIntegrationsList }; @@ -74,23 +81,32 @@ const addSecuritySpecificProps = ({ navigateTo, getAppUrl, card, + onCardClicked, }: { navigateTo: NavigateTo; getAppUrl: GetAppUrl; card: IntegrationCardItem; installedIntegrationList?: IntegrationCardItem[]; + onCardClicked?: (integrationName: string) => void; }): IntegrationCardItem => { const onboardingLink = getAppUrl({ appId: SECURITY_UI_APP_ID, path: ONBOARDING_PATH }); - const integrationRootUrl = getAppUrl({ appId: INTEGRATION_APP_ID }); - const state = { - onCancelNavigateTo: [APP_UI_ID, { path: ONBOARDING_PATH }], - onCancelUrl: onboardingLink, - onSaveNavigateTo: [APP_UI_ID, { path: ONBOARDING_PATH }], - }; + const url = card.url.indexOf(APP_INTEGRATIONS_PATH) >= 0 && onboardingLink ? addPathParamToUrl(card.url, onboardingLink) : card.url; + + const state = { + onCancelNavigateTo: [ + APP_UI_ID, + { path: ONBOARDING_PATH, state: { pkgkey: card.pkgkey, onCancelUrl: onboardingLink } }, + ], + onCancelUrl: onboardingLink, + onSaveNavigateTo: [APP_UI_ID, { path: ONBOARDING_PATH, state: { pkgkey: card.pkgkey } }], + pkgkey: card.pkgkey, + panel: 'overview', // Default to the overview tab on modal opened + }; + return { ...card, titleLineClamp: CARD_TITLE_LINE_CLAMP, @@ -101,10 +117,12 @@ const addSecuritySpecificProps = ({ onCardClick: () => { const trackId = `${TELEMETRY_INTEGRATION_CARD}_${card.id}`; trackOnboardingLinkClick(trackId); + if (url.startsWith(APP_INTEGRATIONS_PATH)) { + onCardClicked?.(card.name); // fix me: type error + navigateTo({ - appId: INTEGRATION_APP_ID, - path: url.slice(integrationRootUrl.length), + path: `${addPathParamToUrl(ONBOARDING_PATH, onboardingLink)}#integrations`, state, }); } else if (url.startsWith('http') || url.startsWith('https')) { @@ -119,15 +137,24 @@ const addSecuritySpecificProps = ({ export const useIntegrationCardList = ({ integrationsList, featuredCardIds, + onCardClicked, }: { integrationsList: IntegrationCardItem[]; featuredCardIds?: string[] | undefined; + onCardClicked?: (integrationName: string) => void; }): IntegrationCardItem[] => { const { navigateTo, getAppUrl } = useNavigation(); const { featuredCards, integrationCards } = useMemo( - () => getFilteredCards({ navigateTo, getAppUrl, integrationsList, featuredCardIds }), - [navigateTo, getAppUrl, integrationsList, featuredCardIds] + () => + getFilteredCards({ + navigateTo, + getAppUrl, + integrationsList, + featuredCardIds, + onCardClicked, + }), + [navigateTo, getAppUrl, integrationsList, featuredCardIds, onCardClicked] ); if (featuredCardIds && featuredCardIds.length > 0) { diff --git a/x-pack/plugins/security_solution/public/onboarding/components/onboarding_context.tsx b/x-pack/plugins/security_solution/public/onboarding/components/onboarding_context.tsx index 17932207c6271..fa50b5ffb123d 100644 --- a/x-pack/plugins/security_solution/public/onboarding/components/onboarding_context.tsx +++ b/x-pack/plugins/security_solution/public/onboarding/components/onboarding_context.tsx @@ -35,8 +35,8 @@ export interface OnboardingContextValue { } const OnboardingContext = createContext(null); -export const OnboardingContextProvider: React.FC> = - React.memo(({ children, spaceId }) => { +export const OnboardingContextProvider: React.FC> = + React.memo(({ children, spaceId, fleet }) => { const config = useFilteredConfig(); const telemetry = useOnboardingTelemetry(); @@ -45,8 +45,8 @@ export const OnboardingContextProvider: React.FC{children}; - }); + return {children}; +}); OnboardingContextProvider.displayName = 'OnboardingContextProvider'; export const useOnboardingContext = () => { diff --git a/x-pack/plugins/security_solution/public/onboarding/index.ts b/x-pack/plugins/security_solution/public/onboarding/index.ts index b20a2777f6ee7..029406bb97a41 100644 --- a/x-pack/plugins/security_solution/public/onboarding/index.ts +++ b/x-pack/plugins/security_solution/public/onboarding/index.ts @@ -6,14 +6,15 @@ */ import type { SecuritySubPlugin } from '../app/types'; +import type { StartPlugins } from '../types'; import { routes } from './routes'; export class Onboarding { public setup() {} - public start(): SecuritySubPlugin { + public start(plugins: StartPlugins): SecuritySubPlugin { return { - routes, + routes: routes(plugins), }; } } diff --git a/x-pack/plugins/security_solution/public/onboarding/routes.tsx b/x-pack/plugins/security_solution/public/onboarding/routes.tsx index b8ac8aba3e90e..e73676db05cec 100644 --- a/x-pack/plugins/security_solution/public/onboarding/routes.tsx +++ b/x-pack/plugins/security_solution/public/onboarding/routes.tsx @@ -8,9 +8,10 @@ import { ONBOARDING_PATH, SecurityPageName } from '../../common/constants'; import type { SecuritySubPluginRoutes } from '../app/types'; import { withSecurityRoutePageWrapper } from '../common/components/security_route_page_wrapper'; +import type { StartPlugins } from '../types'; import { OnboardingPage } from './components/onboarding'; -export const routes: SecuritySubPluginRoutes = [ +export const routes: (plugins: StartPlugins) => SecuritySubPluginRoutes = (plugins) => [ { path: ONBOARDING_PATH, component: withSecurityRoutePageWrapper(OnboardingPage, SecurityPageName.landing), diff --git a/x-pack/plugins/security_solution/scripts/endpoint/common/vm_services.ts b/x-pack/plugins/security_solution/scripts/endpoint/common/vm_services.ts index 084e068768e8f..7b9a6b49c2748 100644 --- a/x-pack/plugins/security_solution/scripts/endpoint/common/vm_services.ts +++ b/x-pack/plugins/security_solution/scripts/endpoint/common/vm_services.ts @@ -57,7 +57,7 @@ const createMultipassVm = async ({ log.info(`Creating VM [${name}] using multipass`); const createResponse = await execa.command( - `multipass launch --name ${name} --disk ${disk} --cpus ${cpus} --memory ${memory}` + `multipass launch --name ${name} --disk ${disk} --cpus ${cpus} --memory ${memory} --network en0` ); log.verbose(`VM [${name}] created successfully using multipass.`, createResponse);